Handle special packet processing correctly.
[silc.git] / lib / silccore / silcmessage.c
1 /*
2
3   silcmessage.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2006 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 "silc.h"
24 #include "silcmessage.h"
25
26 /*************************** Types and definitions **************************/
27
28 /* Calculates padding length for message payload */
29 #define SILC_MESSAGE_PAD(__payloadlen) (16 - ((__payloadlen) % 16))
30
31 /* Header length plus maximum padding length */
32 #define SILC_MESSAGE_HLEN 6 + 16
33
34 /* Maximum message length */
35 #define SILC_MESSAGE_MAX_LEN SILC_PACKET_MAX_LEN - SILC_MESSAGE_HLEN - 16
36
37 /* Payload encoding context */
38 typedef struct {
39   SilcMessageFlags flags;
40   SilcPublicKey public_key;
41   SilcPrivateKey private_key;
42   SilcHash hash;
43   SilcCipher cipher;
44   SilcHmac hmac;
45   unsigned char *iv;
46   SilcUInt16 payload_len;
47 } SilcMessageEncode;
48
49
50 /************************* Static utility functions *************************/
51
52 /* Returns the data length that fits to the packet.  If data length is too
53    big it will be truncated to fit to the payload. */
54
55 static inline
56 SilcUInt32 silc_message_payload_datalen(SilcUInt32 data_len,
57                                         SilcUInt32 header_len,
58                                         SilcUInt32 flags,
59                                         SilcPublicKey public_key,
60                                         SilcPrivateKey private_key)
61 {
62   SilcUInt32 pklen = (flags & SILC_MESSAGE_FLAG_SIGNED && public_key ?
63                       silc_pkcs_public_key_get_len(public_key) : 0);
64   SilcUInt32 prlen = (flags & SILC_MESSAGE_FLAG_SIGNED ?
65                       silc_pkcs_private_key_get_len(private_key) / 8 : 0);
66   SilcUInt32 dlen = data_len + SILC_MESSAGE_HLEN + header_len + pklen + prlen;
67
68   if (dlen > SILC_MESSAGE_MAX_LEN)
69     data_len -= (dlen - SILC_MESSAGE_MAX_LEN);
70
71   return data_len;
72 }
73
74 /* Free signed payload */
75
76 static void silc_message_signed_payload_free(SilcMessageSignedPayload sig)
77 {
78   if (sig->sign_data) {
79     memset(sig->sign_data, 0, sig->sign_len);
80     silc_free(sig->sign_data);
81   }
82   silc_free(sig->pk_data);
83 }
84
85 /* Parses the SILC_MESSAGE_FLAG_SIGNED Payload */
86
87 static SilcBool
88 silc_message_signed_payload_parse(const unsigned char *data,
89                                   SilcUInt32 data_len,
90                                   SilcMessageSignedPayload sig)
91 {
92   SilcBufferStruct buffer;
93   int ret;
94
95   SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload"));
96
97   SILC_LOG_HEXDUMP(("sig payload"), (unsigned char *)data, data_len);
98
99   silc_buffer_set(&buffer, (unsigned char *)data, data_len);
100
101   /* Parse the payload */
102   ret = silc_buffer_unformat(&buffer,
103                              SILC_STR_UI_SHORT(&sig->pk_len),
104                              SILC_STR_UI_SHORT(&sig->pk_type),
105                              SILC_STR_END);
106   if (ret == -1 || sig->pk_len > data_len - 4) {
107     SILC_LOG_DEBUG(("Malformed public key in SILC_MESSAGE_FLAG_SIGNED "
108                     "Payload"));
109     return FALSE;
110   }
111
112   silc_buffer_pull(&buffer, 4);
113   ret = silc_buffer_unformat(&buffer,
114                              SILC_STR_UI_XNSTRING_ALLOC(&sig->pk_data,
115                                                         sig->pk_len),
116                              SILC_STR_UI16_NSTRING_ALLOC(&sig->sign_data,
117                                                          &sig->sign_len),
118                              SILC_STR_END);
119   if (ret == -1 || sig->sign_len > silc_buffer_len(&buffer) -
120       sig->pk_len - 2) {
121     silc_message_signed_payload_free(sig);
122     SILC_LOG_DEBUG(("Malformed SILC_MESSAGE_FLAG_SIGNED Payload"));
123     return FALSE;
124   }
125   silc_buffer_push(&buffer, 4);
126
127   /* Signature must be provided */
128   if (sig->sign_len < 1)  {
129     SILC_LOG_DEBUG(("Malformed signature in SILC_MESSAGE_SIGNED_PAYLOAD "
130                     "Payload"));
131     silc_message_signed_payload_free(sig);
132     return FALSE;
133   }
134
135   return TRUE;
136 }
137
138 /* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */
139
140 static SilcBuffer
141 silc_message_signed_encode_data(const unsigned char *message_payload,
142                                 SilcUInt32 message_payload_len,
143                                 unsigned char *pk,
144                                 SilcUInt32 pk_len, SilcUInt32 pk_type)
145 {
146   SilcBuffer sign;
147
148   sign = silc_buffer_alloc_size(message_payload_len + 4 + pk_len);
149   if (!sign)
150     return NULL;
151
152   silc_buffer_format(sign,
153                      SILC_STR_UI_XNSTRING(message_payload,
154                                           message_payload_len),
155                      SILC_STR_UI_SHORT(pk_len),
156                      SILC_STR_UI_SHORT(pk_type),
157                      SILC_STR_END);
158
159   if (pk && pk_len) {
160     silc_buffer_pull(sign, message_payload_len + 4);
161     silc_buffer_format(sign,
162                        SILC_STR_UI_XNSTRING(pk, pk_len),
163                        SILC_STR_END);
164     silc_buffer_push(sign, message_payload_len + 4);
165   }
166
167   return sign;
168 }
169
170 /* Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the digital
171    signature. */
172
173 static SilcBuffer
174 silc_message_signed_payload_encode(const unsigned char *message_payload,
175                                    SilcUInt32 message_payload_len,
176                                    SilcPublicKey public_key,
177                                    SilcPrivateKey private_key,
178                                    SilcHash hash)
179 {
180   SilcBuffer buffer, sign;
181   unsigned char auth_data[2048 + 1];
182   SilcUInt32 auth_len;
183   unsigned char *pk = NULL;
184   SilcUInt32 pk_len = 0;
185   SilcUInt16 pk_type;
186
187   if (!message_payload || !message_payload_len || !private_key || !hash)
188     return NULL;
189
190   if (public_key) {
191     pk = silc_pkcs_public_key_encode(public_key, &pk_len);
192     if (!pk)
193       return NULL;
194   }
195   pk_type = silc_pkcs_get_type(public_key);
196
197   /* Encode the data to be signed */
198   sign = silc_message_signed_encode_data(message_payload,
199                                          message_payload_len,
200                                          pk, pk_len, pk_type);
201   if (!sign) {
202     silc_free(pk);
203     return NULL;
204   }
205
206   /* Sign the buffer */
207
208   /* Compute the hash and the signature. */
209   if (!silc_pkcs_sign(private_key, sign->data, silc_buffer_len(sign),
210                       auth_data, sizeof(auth_data) - 1, &auth_len, hash)) {
211     SILC_LOG_ERROR(("Could not compute signature"));
212     silc_buffer_clear(sign);
213     silc_buffer_free(sign);
214     silc_free(pk);
215     return NULL;
216   }
217
218   /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */
219
220   buffer = silc_buffer_alloc_size(4 + pk_len + 2 + auth_len);
221   if (!buffer) {
222     silc_buffer_clear(sign);
223     silc_buffer_free(sign);
224     memset(auth_data, 0, sizeof(auth_data));
225     silc_free(pk);
226     return NULL;
227   }
228
229   silc_buffer_format(buffer,
230                      SILC_STR_UI_SHORT(pk_len),
231                      SILC_STR_UI_SHORT(pk_type),
232                      SILC_STR_END);
233
234   if (pk_len && pk) {
235     silc_buffer_pull(buffer, 4);
236     silc_buffer_format(buffer,
237                        SILC_STR_UI_XNSTRING(pk, pk_len),
238                        SILC_STR_END);
239     silc_buffer_push(buffer, 4);
240   }
241
242   silc_buffer_pull(buffer, 4 + pk_len);
243   silc_buffer_format(buffer,
244                      SILC_STR_UI_SHORT(auth_len),
245                      SILC_STR_UI_XNSTRING(auth_data, auth_len),
246                      SILC_STR_END);
247   silc_buffer_push(buffer, 4 + pk_len);
248
249   SILC_LOG_HEXDUMP(("sig payload"), buffer->data, silc_buffer_len(buffer));
250
251   memset(auth_data, 0, sizeof(auth_data));
252   silc_buffer_clear(sign);
253   silc_buffer_free(sign);
254   silc_free(pk);
255
256   return buffer;
257 }
258
259
260 /***************************** Payload parsing ******************************/
261
262 /* Decrypts the Message Payload. The `data' is the actual Message Payload. */
263
264 SilcBool silc_message_payload_decrypt(unsigned char *data,
265                                       size_t data_len,
266                                       SilcBool private_message,
267                                       SilcBool static_key,
268                                       SilcCipher cipher,
269                                       SilcHmac hmac,
270                                       SilcBool check_mac)
271 {
272   SilcUInt32 mac_len, iv_len = 0, block_len;
273   SilcUInt16 len, totlen;
274   unsigned char mac[32], *ivp;
275
276   mac_len = silc_hmac_len(hmac);
277   block_len = silc_cipher_get_block_len(cipher);
278
279   /* IV is present for all channel messages, and private messages when
280      static key (pre-shared key) is used. */
281   if (!private_message || (private_message && static_key))
282     iv_len = block_len;
283
284   if (data_len < (mac_len + iv_len + block_len))
285     return FALSE;
286
287   if (check_mac) {
288     /* Check the MAC of the message */
289     SILC_LOG_DEBUG(("Checking message MAC"));
290     silc_hmac_init(hmac);
291     silc_hmac_update(hmac, data, data_len - mac_len);
292     silc_hmac_final(hmac, mac, &mac_len);
293     if (memcmp(data + (data_len - mac_len), mac, mac_len)) {
294       SILC_LOG_DEBUG(("Message MAC does not match"));
295       return FALSE;
296     }
297     SILC_LOG_DEBUG(("MAC is Ok"));
298   }
299
300   /* Decrypt first only one block to get the header and then rest of
301      the data.  This is done because there might be unencrypted data at
302      the end and we don't know the encrypted length yet. */
303
304   /* Get pointer to the IV */
305   ivp = (iv_len ? data + (data_len - iv_len - mac_len) :
306          silc_cipher_get_iv(cipher));
307
308   /* Decrypt block */
309   if (!silc_cipher_decrypt(cipher, data, data, block_len, ivp)) {
310     SILC_ASSERT(FALSE);
311     return FALSE;
312   }
313
314   /* Get the payload length and decrypt rest */
315   totlen = 2;
316   SILC_GET16_MSB(len, data + totlen);
317   totlen += 2 + len;
318   if (totlen + iv_len + mac_len + 2 > data_len)
319     return FALSE;
320   totlen += 2;
321   if (totlen >= block_len)
322     if (!silc_cipher_decrypt(cipher, data + block_len, data + block_len,
323                              (totlen - block_len) + SILC_MESSAGE_PAD(totlen),
324                              ivp)) {
325       SILC_ASSERT(FALSE);
326       return FALSE;
327     }
328
329   return TRUE;
330 }
331
332 /* Parses Message Payload returning new payload structure.  This also
333    decrypts it and checks the MAC. */
334
335 SilcMessagePayload
336 silc_message_payload_parse(unsigned char *payload,
337                            SilcUInt32 payload_len,
338                            SilcBool private_message,
339                            SilcBool static_key,
340                            SilcCipher cipher,
341                            SilcHmac hmac,
342                            SilcStack stack,
343                            SilcBool no_allocation,
344                            SilcMessagePayload message)
345 {
346   SilcBufferStruct buffer;
347   SilcMessagePayload newp = NULL;
348   int ret;
349   SilcUInt32 mac_len = 0, iv_len = 0;
350
351   SILC_LOG_DEBUG(("Parsing Message Payload"));
352
353   silc_buffer_set(&buffer, payload, payload_len);
354
355   /* Decrypt the payload */
356   if (cipher) {
357     ret = silc_message_payload_decrypt(buffer.data, silc_buffer_len(&buffer),
358                                        private_message, static_key,
359                                        cipher, hmac, TRUE);
360     if (ret == FALSE)
361       return NULL;
362   }
363
364   if (hmac)
365     mac_len = silc_hmac_len(hmac);
366
367   /* IV is present for all channel messages, and private messages when
368      static key (pre-shared key) is used. */
369   if (cipher && (!private_message || (private_message && static_key)))
370     iv_len = silc_cipher_get_block_len(cipher);
371
372   if (!message) {
373     newp = message = silc_calloc(1, sizeof(*newp));
374     if (!newp)
375       return NULL;
376   }
377   memset(message, 0, sizeof(*message));
378   message->allocated = (stack || no_allocation ? FALSE : TRUE);
379
380   /* Parse the Message Payload. */
381   if (!no_allocation)
382     ret = silc_buffer_sunformat(stack, &buffer,
383                           SILC_STR_UI_SHORT(&message->flags),
384                           SILC_STR_UI16_NSTRING_ALLOC(&message->data,
385                                                       &message->data_len),
386                           SILC_STR_UI16_NSTRING_ALLOC(&message->pad,
387                                                       &message->pad_len),
388                           SILC_STR_END);
389   else
390     ret = silc_buffer_unformat(&buffer,
391                                SILC_STR_UI_SHORT(&message->flags),
392                                SILC_STR_UI16_NSTRING(&message->data,
393                                                      &message->data_len),
394                                SILC_STR_UI16_NSTRING(&message->pad,
395                                                      &message->pad_len),
396                                SILC_STR_END);
397   if (ret == -1)
398     goto err;
399
400   if ((message->data_len > silc_buffer_len(&buffer) - 6 - mac_len - iv_len) ||
401       (message->pad_len + message->data_len > silc_buffer_len(&buffer) -
402        6 - mac_len - iv_len)) {
403     SILC_LOG_ERROR(("Incorrect Message Payload in packet"));
404     goto err;
405   }
406
407   /* Parse Signed Message Payload if provided */
408   if (message->flags & SILC_MESSAGE_FLAG_SIGNED &&
409       message->data_len + message->pad_len + 6 + mac_len +
410       iv_len < silc_buffer_len(&buffer)) {
411     if (!silc_message_signed_payload_parse(buffer.data + 6 +
412                                            message->data_len +
413                                            message->pad_len,
414                                            silc_buffer_len(&buffer) -
415                                            iv_len - mac_len - 6 -
416                                            message->data_len -
417                                            message->pad_len,
418                                            &message->sig))
419       goto err;
420   }
421
422   /* Parse MAC from the payload */
423   if (mac_len)
424     message->mac = buffer.data + (silc_buffer_len(&buffer) - mac_len);
425
426   return newp;
427
428  err:
429   if (newp)
430     silc_message_payload_free(newp);
431   return NULL;
432 }
433
434
435 /***************************** Payload encoding *****************************/
436
437 /* This function is used to encrypt the Messsage Payload which is
438    the `data' and `data_len'.  This is used internally by the Message
439    Payload encoding routines but application may call this too if needed.
440    The `true_len' is the data length which is used to create MAC out of. */
441
442 SilcBool silc_message_payload_encrypt(unsigned char *data,
443                                       SilcUInt32 data_len,
444                                       SilcUInt32 true_len,
445                                       unsigned char *iv,
446                                       SilcCipher cipher,
447                                       SilcHmac hmac)
448 {
449   /* Encrypt payload of the packet */
450   if (!silc_cipher_encrypt(cipher, data, data, data_len, iv))
451     return FALSE;
452
453   /* Compute the MAC of the encrypted message data */
454   silc_hmac_init(hmac);
455   silc_hmac_update(hmac, data, true_len);
456   silc_hmac_final(hmac, data + true_len, NULL);
457
458   return TRUE;
459 }
460
461 /* Encrypt message payload */
462
463 static int silc_message_payload_encode_encrypt(SilcBuffer buffer,
464                                                void *value, void *context)
465 {
466   SilcMessageEncode *e = context;
467   SilcUInt32 mac_len;
468
469   if (!e->cipher || !e->hmac)
470     return 0;
471
472   mac_len = silc_hmac_len(e->hmac);
473   if (!silc_buffer_enlarge(buffer, mac_len))
474     return -1;
475
476   if (!silc_message_payload_encrypt(buffer->head,
477                                     e->payload_len,
478                                     silc_buffer_headlen(buffer),
479                                     e->iv, e->cipher, e->hmac))
480     return -1;
481
482   return mac_len;
483 }
484
485 /* Compute message signature */
486
487 static int silc_message_payload_encode_sig(SilcBuffer buffer,
488                                            void *value, void *context)
489 {
490   SilcMessageEncode *e = context;
491   SilcBuffer sig;
492   int len;
493
494   if (!(e->flags & SILC_MESSAGE_FLAG_SIGNED))
495     return 0;
496
497   sig = silc_message_signed_payload_encode(buffer->head,
498                                            silc_buffer_headlen(buffer),
499                                            e->public_key, e->private_key,
500                                            e->hash);
501   if (!sig)
502     return -1;
503
504   len = silc_buffer_format(buffer,
505                            SILC_STR_DATA(silc_buffer_data(sig),
506                                          silc_buffer_len(sig)),
507                            SILC_STR_END);
508   if (len < 0) {
509     silc_buffer_free(sig);
510     return -1;
511   }
512
513   silc_buffer_free(sig);
514   return len;
515 }
516
517 /* Encodes Message Payload into a buffer and returns it. */
518
519 SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
520                                        const unsigned char *data,
521                                        SilcUInt32 data_len,
522                                        SilcBool generate_iv,
523                                        SilcBool private_message,
524                                        SilcCipher cipher,
525                                        SilcHmac hmac,
526                                        SilcRng rng,
527                                        SilcPublicKey public_key,
528                                        SilcPrivateKey private_key,
529                                        SilcHash hash,
530                                        SilcBuffer buffer)
531 {
532   SilcUInt32 pad_len = 0, mac_len = 0, iv_len = 0;
533   unsigned char pad[16], iv[SILC_CIPHER_MAX_IV_SIZE];
534   SilcBuffer buf = NULL;
535   SilcMessageEncode e;
536   int i;
537
538   SILC_LOG_DEBUG(("Encoding Message Payload"));
539
540   if (!data_len)
541     return NULL;
542   if (!private_message && (!cipher || !hmac))
543     return NULL;
544
545   if (!buffer) {
546     buf = buffer = silc_buffer_alloc(0);
547     if (!buf)
548       return NULL;
549   }
550   silc_buffer_reset(buffer);
551
552   /* For channel messages IV is always generated */
553   if (!private_message && !generate_iv)
554     generate_iv = TRUE;
555
556   /* Generate IV */
557   if (cipher && generate_iv) {
558     iv_len = silc_cipher_get_block_len(cipher);
559     if (rng) {
560       for (i = 0; i < iv_len; i++) iv[i] = silc_rng_get_byte_fast(rng);
561     } else {
562       for (i = 0; i < iv_len; i++) iv[i] = silc_rng_global_get_byte_fast();
563     }
564   }
565
566   if (hmac)
567     mac_len = silc_hmac_len(hmac);
568   data_len = silc_message_payload_datalen(data_len, mac_len + iv_len, flags,
569                                           public_key, private_key);
570
571   /* Calculate length of padding. IV is not included into the calculation
572      since it is not encrypted. */
573   pad_len = SILC_MESSAGE_PAD(6 + data_len);
574
575   /* Generate padding */
576   if (cipher) {
577     if (rng) {
578       for (i = 0; i < pad_len; i++) pad[i] = silc_rng_get_byte_fast(rng);
579     } else {
580       for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte_fast();
581     }
582   }
583
584   e.flags = flags;
585   e.public_key = public_key;
586   e.private_key = private_key;
587   e.hash = hash;
588   e.cipher = cipher;
589   e.hmac = hmac;
590   e.iv = iv_len ? iv : NULL;
591   e.payload_len = 6 + data_len + pad_len;
592
593   /* Encode the Message Payload */
594   if (silc_buffer_format(buffer,
595                          SILC_STR_UI_SHORT(flags),
596                          SILC_STR_UI_SHORT(data_len),
597                          SILC_STR_DATA(data, data_len),
598                          SILC_STR_UI_SHORT(pad_len),
599                          SILC_STR_DATA(pad, pad_len),
600                          SILC_STR_FUNC(silc_message_payload_encode_sig,
601                                        NULL, &e),
602                          SILC_STR_DATA(iv, iv_len),
603                          SILC_STR_FUNC(silc_message_payload_encode_encrypt,
604                                        NULL, &e),
605                          SILC_STR_END) < 0) {
606     silc_buffer_free(buf);
607     return NULL;
608   }
609
610   return buffer;
611 }
612
613 /* Free's Message Payload */
614
615 void silc_message_payload_free(SilcMessagePayload payload)
616 {
617   if (payload->data) {
618     memset(payload->data, 0, payload->data_len);
619     if (payload->allocated)
620       silc_free(payload->data);
621   }
622   if (payload->allocated) {
623     silc_free(payload->pad);
624     silc_free(payload);
625   }
626   silc_message_signed_payload_free(&payload->sig);
627 }
628
629 /* Return flags */
630
631 SilcMessageFlags silc_message_get_flags(SilcMessagePayload payload)
632 {
633   return payload->flags;
634 }
635
636 /* Return data */
637
638 unsigned char *silc_message_get_data(SilcMessagePayload payload,
639                                      SilcUInt32 *data_len)
640 {
641   if (data_len)
642     *data_len = payload->data_len;
643   return payload->data;
644 }
645
646 /* Return MAC. The caller knows the length of the MAC */
647
648 unsigned char *silc_message_get_mac(SilcMessagePayload payload)
649 {
650   return payload->mac;
651 }
652
653 /* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
654
655 SilcAuthResult silc_message_signed_verify(SilcMessagePayload message,
656                                           SilcPublicKey remote_public_key,
657                                           SilcHash hash)
658 {
659   int ret = SILC_AUTH_FAILED;
660   SilcBuffer sign, tmp;
661   SilcMessageSignedPayload sig = &message->sig;
662
663   if (!(message->flags & SILC_MESSAGE_FLAG_SIGNED) ||
664       !sig->sign_len || !remote_public_key || !hash)
665     return ret;
666
667   /* Generate the signature verification data, the Message Payload */
668   tmp = silc_buffer_alloc_size(6 + message->data_len + message->pad_len);
669   silc_buffer_format(tmp,
670                      SILC_STR_UI_SHORT(message->flags),
671                      SILC_STR_UI_SHORT(message->data_len),
672                      SILC_STR_UI_XNSTRING(message->data, message->data_len),
673                      SILC_STR_UI_SHORT(message->pad_len),
674                      SILC_STR_UI_XNSTRING(message->pad, message->pad_len),
675                      SILC_STR_END);
676   sign = silc_message_signed_encode_data(tmp->data, silc_buffer_len(tmp),
677                                          sig->pk_data, sig->pk_len,
678                                          sig->pk_type);
679   silc_buffer_clear(tmp);
680   silc_buffer_free(tmp);
681
682   if (!sign)
683     return ret;
684
685   /* Verify the authentication data */
686   if (!silc_pkcs_verify(remote_public_key, sig->sign_data, sig->sign_len,
687                         silc_buffer_data(sign), silc_buffer_len(sign), hash)) {
688     silc_buffer_clear(sign);
689     silc_buffer_free(sign);
690     SILC_LOG_DEBUG(("Signature verification failed"));
691     return ret;
692   }
693
694   ret = SILC_AUTH_OK;
695
696   silc_buffer_clear(sign);
697   silc_buffer_free(sign);
698
699   SILC_LOG_DEBUG(("Signature verification successful"));
700
701   return ret;
702 }
703
704 /* Return the public key from the payload */
705
706 SilcPublicKey
707 silc_message_signed_get_public_key(SilcMessagePayload payload,
708                                    const unsigned char **pk_data,
709                                    SilcUInt32 *pk_data_len)
710 {
711   SilcPublicKey pk;
712   SilcMessageSignedPayload sig = &payload->sig;
713
714   if (!sig->pk_data)
715     return NULL;
716
717   if (!silc_pkcs_public_key_alloc(sig->pk_type, sig->pk_data,
718                                   sig->pk_len, &pk))
719     return NULL;
720
721   if (pk_data)
722     *pk_data = sig->pk_data;
723   if (pk_data_len)
724     *pk_data_len = sig->pk_len;
725
726   return pk;
727 }