e3fd64f970cb17556abd27cb35a6eec618429aa1
[silc.git] / lib / silccore / silcmessage.c
1 /*
2
3   silcmessage.c 
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2002 Pekka Riikonen
8
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.
12
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.
17
18 */
19 /* Implementation of the Message Payload used as channel messages and
20    private messages. */
21 /* $Id$ */
22
23 #include "silcincludes.h"
24 #include "silcmessage.h"
25
26 /******************************************************************************
27
28                                Message Payload
29
30 ******************************************************************************/
31
32 /* Calculates padding length for message payload */
33 #define SILC_MESSAGE_PAD(__payloadlen) (16 - ((__payloadlen) % 16))
34
35 /* Header length plus maximum padding length */
36 #define SILC_MESSAGE_HLEN 6 + 16
37
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)
45
46 /* Message Payload structure. Contents of this structure is parsed
47    from SILC packets. */
48 struct SilcMessagePayloadStruct {
49   SilcMessageFlags flags;
50   SilcUInt16 data_len;
51   SilcUInt16 pad_len;
52   SilcUInt16 iv_len;
53   unsigned char *data;
54   unsigned char *pad;
55   unsigned char *iv;
56   unsigned char *mac;
57   /*SilcMessageSignedPayload sig;*/
58 };
59
60 /* Decrypts the Message Payload. The `data' is the actual Message Payload */
61
62 bool silc_message_payload_decrypt(unsigned char *data,
63                                   size_t data_len,
64                                   bool private_message,
65                                   bool static_key,
66                                   SilcCipher cipher,
67                                   SilcHmac hmac,
68                                   bool check_mac)
69 {
70   SilcUInt32 mac_len = 0, iv_len = 0;
71   unsigned char *mac, mac2[32];
72
73   mac_len = silc_hmac_len(hmac);
74
75   /* IV is present for channel messages and private messages when static
76      key (pre-shared key) is used. */
77   if (!private_message || (private_message && static_key))
78     iv_len = silc_cipher_get_block_len(cipher);
79
80   if (data_len < mac_len)
81     return FALSE;
82
83   if (check_mac) {
84     /* Take the MAC */
85     mac = data + (data_len - mac_len);
86
87     /* Check the MAC of the message */
88     SILC_LOG_DEBUG(("Checking message MAC"));
89     silc_hmac_init(hmac);
90     silc_hmac_update(hmac, data, data_len - mac_len);
91     silc_hmac_final(hmac, mac2, &mac_len);
92     if (memcmp(mac, mac2, mac_len)) {
93       SILC_LOG_DEBUG(("Message MAC does not match"));
94       return FALSE;
95     }
96     SILC_LOG_DEBUG(("MAC is Ok"));
97   }
98
99   /* Decrypt the message */
100   silc_cipher_decrypt(cipher, data, data, data_len - iv_len - mac_len,
101                       (iv_len ? data + (data_len - iv_len - mac_len) : NULL));
102   return TRUE;
103 }
104
105 /* Parses Message Payload returning new payload structure.  This also
106    decrypts it and checks the MAC. */
107
108 SilcMessagePayload 
109 silc_message_payload_parse(unsigned char *payload,
110                            SilcUInt32 payload_len,
111                            bool private_message,
112                            bool static_key,
113                            SilcCipher cipher,
114                            SilcHmac hmac)
115 {
116   SilcBufferStruct buffer;
117   SilcMessagePayload newp;
118   int ret;
119   SilcUInt32 mac_len = 0, iv_len = 0;
120
121   SILC_LOG_DEBUG(("Parsing Message Payload"));
122
123   silc_buffer_set(&buffer, payload, payload_len);
124
125   /* Decrypt the payload */
126   if (cipher) {
127     ret = silc_message_payload_decrypt(buffer.data, buffer.len,
128                                        private_message, static_key,
129                                        cipher, hmac, TRUE);
130     if (ret == FALSE)
131       return NULL;
132   }
133
134   if (hmac)
135     mac_len = silc_hmac_len(hmac);
136
137   /* IV is present for channel messages and private messages when static
138      key (pre-shared key) is used. */
139   if (cipher && (!private_message || (private_message && static_key)))
140     iv_len = silc_cipher_get_block_len(cipher);
141
142   newp = silc_calloc(1, sizeof(*newp));
143   if (!newp)
144     return NULL;
145
146   /* Parse the Message Payload. */
147   ret = silc_buffer_unformat(&buffer,
148                              SILC_STR_UI_SHORT(&newp->flags),
149                              SILC_STR_UI16_NSTRING_ALLOC(&newp->data, 
150                                                          &newp->data_len),
151                              SILC_STR_UI16_NSTRING_ALLOC(&newp->pad, 
152                                                          &newp->pad_len),
153                              SILC_STR_UI_XNSTRING(&newp->iv, iv_len),
154                              SILC_STR_UI_XNSTRING(&newp->mac, mac_len),
155                              SILC_STR_END);
156   if (ret == -1)
157     goto err;
158
159   if ((newp->data_len > buffer.len - 6 - mac_len - iv_len) ||
160       (newp->pad_len + newp->data_len > buffer.len - 6 - mac_len - iv_len)) {
161     SILC_LOG_ERROR(("Incorrect Message Payload in packet"));
162     goto err;
163   }
164
165   newp->iv_len = iv_len;
166
167   return newp;
168
169  err:
170   silc_message_payload_free(newp);
171   return NULL;
172 }
173
174 /* This function is used to encrypt the Messsage Payload which is
175    the `data' and `data_len'.  This is used internally by the Message
176    Payload encoding routines but application may call this too if needed. 
177    The `data_len' is the data lenght which is used to create MAC out of. */
178
179 bool silc_message_payload_encrypt(unsigned char *data,
180                                   SilcUInt32 data_len,
181                                   unsigned char *iv,
182                                   SilcUInt32 iv_len,
183                                   SilcCipher cipher,
184                                   SilcHmac hmac)
185 {
186   unsigned char mac[32];
187   SilcUInt32 mac_len;
188   SilcBufferStruct buf;
189
190   /* Encrypt payload of the packet. If the IV is added to packet do
191      not encrypt that. */
192   silc_cipher_encrypt(cipher, data, data, data_len - iv_len,
193                       iv_len ? iv : NULL);
194
195   /* Compute the MAC of the encrypted message data */
196   silc_hmac_init(hmac);
197   silc_hmac_update(hmac, data, data_len);
198   silc_hmac_final(hmac, mac, &mac_len);
199
200   /* Put rest of the data to the payload */
201   silc_buffer_set(&buf, data, data_len + mac_len);
202   silc_buffer_pull(&buf, data_len);
203   silc_buffer_put(&buf, mac, mac_len);
204
205   return TRUE;
206 }
207
208 /* Encodes Message Payload into a buffer and returns it. */
209
210 SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
211                                        const unsigned char *data,
212                                        SilcUInt32 data_len,
213                                        bool generate_iv,
214                                        bool private_message,
215                                        SilcCipher cipher,
216                                        SilcHmac hmac,
217                                        SilcRng rng)
218 {
219   int i;
220   SilcBuffer buffer;
221   SilcUInt32 len, pad_len = 0, mac_len = 0, iv_len = 0;
222   unsigned char pad[16], iv[SILC_CIPHER_MAX_IV_SIZE];
223
224   SILC_LOG_DEBUG(("Encoding Message Payload"));
225
226   if (!data_len)
227     return NULL;
228
229   /* For channel messages IV is always generated */
230   if (!private_message && !generate_iv)
231     generate_iv = TRUE;
232
233   /* Generate IV */
234   if (cipher && generate_iv) {
235     iv_len = silc_cipher_get_block_len(cipher);
236     if (rng) {
237       for (i = 0; i < iv_len; i++) iv[i] = silc_rng_get_byte_fast(rng);
238     } else {
239       for (i = 0; i < iv_len; i++) iv[i] = silc_rng_global_get_byte_fast();
240     }
241   }
242
243   if (hmac)
244     mac_len = silc_hmac_len(hmac);
245   data_len = SILC_MESSAGE_DATALEN(data_len, mac_len + iv_len);
246
247   /* Calculate length of padding. IV is not included into the calculation
248      since it is not encrypted. */
249   len = 6 + data_len;
250   pad_len = SILC_MESSAGE_PAD(len);
251
252   /* Allocate payload buffer */
253   len += pad_len + iv_len + mac_len;
254   buffer = silc_buffer_alloc(len);
255   if (!buffer)
256     return NULL;
257
258   /* Generate padding */
259   if (cipher) {
260     if (rng) {
261       for (i = 0; i < pad_len; i++) pad[i] = silc_rng_get_byte_fast(rng);
262     } else {
263       for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte_fast();
264     }
265   }
266
267   /* Encode the Message Payload */
268   silc_buffer_pull_tail(buffer, 6 + data_len + pad_len + iv_len);
269   silc_buffer_format(buffer, 
270                      SILC_STR_UI_SHORT(flags),
271                      SILC_STR_UI_SHORT(data_len),
272                      SILC_STR_UI_XNSTRING(data, data_len),
273                      SILC_STR_UI_SHORT(pad_len),
274                      SILC_STR_UI_XNSTRING(pad, pad_len),
275                      SILC_STR_UI_XNSTRING(iv, iv_len),
276                      SILC_STR_END);
277
278   memset(pad, 0, sizeof(pad));
279
280   /* Now encrypt the Message Payload */
281   if (cipher) {
282     if (!silc_message_payload_encrypt(buffer->data, buffer->len,
283                                       iv, iv_len, cipher, hmac)) {
284       silc_buffer_free(buffer);
285       return NULL;
286     }
287   }
288   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer) - buffer->len);
289
290   return buffer;
291 }
292
293 /* Free's Message Payload */
294
295 void silc_message_payload_free(SilcMessagePayload payload)
296 {
297   if (payload->data) {
298     memset(payload->data, 0, payload->data_len);
299     silc_free(payload->data);
300   }
301   silc_free(payload->pad);
302   silc_free(payload);
303 }
304
305 /* Return flags */
306
307 SilcMessageFlags silc_message_get_flags(SilcMessagePayload payload)
308 {
309   return payload->flags;
310 }
311
312 /* Return data */
313
314 unsigned char *silc_message_get_data(SilcMessagePayload payload,
315                                      SilcUInt32 *data_len)
316 {
317   if (data_len)
318     *data_len = payload->data_len;
319   return payload->data;
320 }
321
322 /* Return MAC. The caller knows the length of the MAC */
323
324 unsigned char *silc_message_get_mac(SilcMessagePayload payload)
325 {
326   return payload->mac;
327 }
328
329 /* Return IV. The caller knows the length of the IV */
330
331 unsigned char *silc_message_get_iv(SilcMessagePayload payload)
332 {
333   return payload->iv;
334 }
335
336 /******************************************************************************
337
338                      SILC_MESSAGE_FLAG_SIGNED Payload
339
340 ******************************************************************************/
341
342 /* The SILC_MESSAGE_FLAG_SIGNED Payload */
343 struct SilcMessageSignedPayloadStruct {
344   SilcUInt16 pk_len;
345   SilcUInt16 pk_type;
346   SilcUInt16 sign_len;
347   unsigned char *pk_data;
348   unsigned char *sign_data;
349 };
350
351 /* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */
352
353 static SilcBuffer
354 silc_message_signed_encode_data(const unsigned char *message_payload,
355                                 SilcUInt32 message_payload_len,
356                                 unsigned char *pk,
357                                 SilcUInt32 pk_len, SilcUInt32 pk_type)
358 {
359   SilcBuffer sign;
360
361   sign = silc_buffer_alloc_size(message_payload_len + 4 + pk_len);
362   if (!sign)
363     return NULL;
364
365   silc_buffer_format(sign,
366                      SILC_STR_UI_XNSTRING(message_payload,
367                                           message_payload_len),
368                      SILC_STR_UI_SHORT(pk_len),
369                      SILC_STR_UI_SHORT(pk_type),
370                      SILC_STR_END);
371
372   if (pk && pk_len) {
373     silc_buffer_pull(sign, message_payload_len + 4);
374     silc_buffer_format(sign,
375                        SILC_STR_UI_XNSTRING(pk, pk_len),
376                        SILC_STR_END);
377     silc_buffer_push(sign, message_payload_len + 4);
378   }
379
380   return sign;
381 }
382
383 /* Parses the SILC_MESSAGE_FLAG_SIGNED Payload */
384
385 SilcMessageSignedPayload
386 silc_message_signed_payload_parse(const unsigned char *data,
387                                   SilcUInt32 data_len)
388 {
389   SilcMessageSignedPayload sig;
390   SilcBufferStruct buffer;
391   int ret;
392
393   SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload"));
394
395   silc_buffer_set(&buffer, (unsigned char *)data, data_len);
396   sig = silc_calloc(1, sizeof(*sig));
397   if (!sig)
398     return NULL;
399
400   /* Parse the payload */
401   ret = silc_buffer_unformat(&buffer,
402                              SILC_STR_UI_SHORT(&sig->pk_len),
403                              SILC_STR_UI_SHORT(&sig->pk_type),
404                              SILC_STR_END);
405   if (ret == -1 || sig->pk_len > data_len - 4) {
406     silc_message_signed_payload_free(sig);
407     return NULL;
408   }
409
410   silc_buffer_pull(&buffer, 4);
411   ret = silc_buffer_unformat(&buffer,
412                              SILC_STR_UI_XNSTRING_ALLOC(&sig->pk_data,
413                                                         sig->pk_len),
414                              SILC_STR_UI16_NSTRING_ALLOC(&sig->sign_data,
415                                                          &sig->sign_len),
416                              SILC_STR_END);
417   if (ret == -1) {
418     silc_message_signed_payload_free(sig);
419     return NULL;
420   }
421   silc_buffer_push(&buffer, 4);
422
423   /* Signature must be provided */
424   if (sig->sign_len < 1)  {
425     silc_message_signed_payload_free(sig);
426     return NULL;
427   }
428
429   return sig;
430 }
431
432 /* Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the digital
433    signature. */
434
435 SilcBuffer
436 silc_message_signed_payload_encode(const unsigned char *message_payload,
437                                    SilcUInt32 message_payload_len,
438                                    SilcPublicKey public_key,
439                                    SilcPrivateKey private_key,
440                                    SilcHash hash,
441                                    bool include_public_key)
442 {
443   SilcBuffer buffer, sign;
444   SilcPKCS pkcs;
445   unsigned char auth_data[2048];
446   SilcUInt32 auth_len;
447   unsigned char *pk = NULL;
448   SilcUInt32 pk_len = 0;
449   SilcUInt16 pk_type;
450
451   if (!message_payload || !message_payload_len || !private_key || !hash)
452     return NULL;
453   if (include_public_key && !public_key)
454     return NULL;
455
456   if (include_public_key)
457     pk = silc_pkcs_public_key_encode(public_key, &pk_len);
458
459   /* Now we support only SILC style public key */
460   pk_type = SILC_SKE_PK_TYPE_SILC;
461
462   /* Encode the data to be signed */
463   sign = silc_message_signed_encode_data(message_payload,
464                                          message_payload_len,
465                                          pk, pk_len, pk_type);
466   if (!sign) {
467     silc_free(pk);
468     return NULL;
469   }
470
471   /* Sign the buffer */
472
473   /* Allocate PKCS object */
474   if (!silc_pkcs_alloc(private_key->name, &pkcs)) {
475     silc_buffer_clear(sign);
476     silc_buffer_free(sign);
477     silc_free(pk);
478     return NULL;
479   }
480   silc_pkcs_private_key_set(pkcs, private_key);
481
482   /* Compute the hash and the signature. */
483   if (silc_pkcs_get_key_len(pkcs) / 8 > sizeof(auth_data) - 1 ||
484       !silc_pkcs_sign_with_hash(pkcs, hash, sign->data, sign->len, auth_data,
485                                 &auth_len)) {
486     silc_buffer_clear(sign);
487     silc_buffer_free(sign);
488     silc_pkcs_free(pkcs);
489     silc_free(pk);
490     return NULL;
491   }
492
493   /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */
494
495   buffer = silc_buffer_alloc_size(4 + pk_len + 2 + auth_len);
496   if (!buffer) {
497     silc_buffer_clear(sign);
498     silc_buffer_free(sign);
499     silc_pkcs_free(pkcs);
500     memset(auth_data, 0, sizeof(auth_data));
501     silc_free(pk);
502     return NULL;
503   }
504
505   silc_buffer_format(sign,
506                      SILC_STR_UI_SHORT(pk_len),
507                      SILC_STR_UI_SHORT(pk_type),
508                      SILC_STR_END);
509
510   if (pk_len && pk) {
511     silc_buffer_pull(sign, 4);
512     silc_buffer_format(sign,
513                        SILC_STR_UI_XNSTRING(pk, pk_len),
514                        SILC_STR_END);
515     silc_buffer_push(sign, 4);
516   }
517
518   silc_buffer_pull(sign, 4 + pk_len);
519   silc_buffer_format(sign,
520                      SILC_STR_UI_SHORT(auth_len),
521                      SILC_STR_UI_XNSTRING(auth_data, auth_len),
522                      SILC_STR_END);
523   silc_buffer_push(sign, 4 + pk_len);
524
525   memset(auth_data, 0, sizeof(auth_data));
526   silc_pkcs_free(pkcs);
527   silc_buffer_clear(sign);
528   silc_buffer_free(sign);
529   silc_free(pk);
530
531   return buffer;
532 }
533
534 /* Free the payload */
535
536 void silc_message_signed_payload_free(SilcMessageSignedPayload sig)
537 {
538   if (sig) {
539     memset(sig->sign_data, 0, sig->sign_len);
540     silc_free(sig->sign_data);
541     silc_free(sig->pk_data);
542     silc_free(sig);
543   }
544 }
545
546 /* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
547
548 int silc_message_signed_verify(SilcMessageSignedPayload sig,
549                                SilcMessagePayload message,
550                                SilcPublicKey remote_public_key,
551                                SilcHash hash)
552 {
553   int ret = SILC_AUTH_FAILED;
554   SilcBuffer sign;
555   SilcPKCS pkcs;
556   SilcBuffer tmp;
557   
558   if (!sig || !remote_public_key || !hash)
559     return ret;
560
561   /* Generate the signature verification data, the Message Payload */
562   tmp = silc_buffer_alloc_size(6 + message->data_len + message->pad_len +
563                                message->iv_len);
564   silc_buffer_format(tmp,
565                      SILC_STR_UI_SHORT(message->flags),
566                      SILC_STR_UI_SHORT(message->data_len),
567                      SILC_STR_UI_XNSTRING(message->data, message->data_len),
568                      SILC_STR_UI_SHORT(message->pad_len),
569                      SILC_STR_UI_XNSTRING(message->pad, message->pad_len),
570                      SILC_STR_UI_XNSTRING(message->iv, message->iv_len),
571                      SILC_STR_END);
572   sign = silc_message_signed_encode_data(tmp->data, tmp->len,
573                                          sig->pk_data, sig->pk_len,
574                                          sig->pk_type);
575   silc_buffer_clear(tmp);
576   silc_buffer_free(tmp);
577   
578   if (!sign)
579     return ret;
580   
581   /* Allocate PKCS object */
582   if (!silc_pkcs_alloc(remote_public_key->name, &pkcs)) {
583     silc_buffer_clear(sign);
584     silc_buffer_free(sign);
585     return ret;
586   }
587   silc_pkcs_public_key_set(pkcs, remote_public_key);
588
589   /* Verify the authentication data */
590   if (!silc_pkcs_verify_with_hash(pkcs, hash, sig->sign_data,
591                                   sig->sign_len,
592                                   sign->data, sign->len)) {
593
594     silc_buffer_clear(sign);
595     silc_buffer_free(sign);
596     silc_pkcs_free(pkcs);
597     SILC_LOG_DEBUG(("Signature verification failed"));
598     return ret;
599   }
600
601   ret = SILC_AUTH_OK;
602
603   silc_buffer_clear(sign);
604   silc_buffer_free(sign);
605   silc_pkcs_free(pkcs);
606
607   SILC_LOG_DEBUG(("Signature verification successful"));
608
609   return ret;
610 }
611
612 /* Return the public key from the payload */
613
614 SilcPublicKey
615 silc_message_signed_get_public_key(SilcMessageSignedPayload sig)
616 {
617   SilcPublicKey pk;
618
619   if (!sig->pk_data || !silc_pkcs_public_key_decode(sig->pk_data,
620                                                     sig->pk_len, &pk))
621     return NULL;
622
623   return pk;
624 }