Removed signed payload encoding and parsing from public API,
[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))
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     return FALSE;
311
312   /* Get the payload length and decrypt rest */
313   totlen = 2;
314   SILC_GET16_MSB(len, data + totlen);
315   totlen += 2 + len;
316   if (totlen + iv_len + mac_len + 2 > data_len)
317     return FALSE;
318   totlen += 2;
319   if (totlen >= block_len)
320     if (!silc_cipher_decrypt(cipher, data + block_len, data + block_len,
321                              (totlen - block_len) + SILC_MESSAGE_PAD(totlen),
322                              ivp))
323       return FALSE;
324
325   return TRUE;
326 }
327
328 /* Parses Message Payload returning new payload structure.  This also
329    decrypts it and checks the MAC. */
330
331 SilcMessagePayload
332 silc_message_payload_parse(unsigned char *payload,
333                            SilcUInt32 payload_len,
334                            SilcBool private_message,
335                            SilcBool static_key,
336                            SilcCipher cipher,
337                            SilcHmac hmac,
338                            SilcStack stack,
339                            SilcBool no_allocation,
340                            SilcMessagePayload message)
341 {
342   SilcBufferStruct buffer;
343   SilcMessagePayload newp = NULL;
344   int ret;
345   SilcUInt32 mac_len = 0, iv_len = 0;
346
347   SILC_LOG_DEBUG(("Parsing Message Payload"));
348
349   silc_buffer_set(&buffer, payload, payload_len);
350
351   /* Decrypt the payload */
352   if (cipher) {
353     ret = silc_message_payload_decrypt(buffer.data, silc_buffer_len(&buffer),
354                                        private_message, static_key,
355                                        cipher, hmac, TRUE);
356     if (ret == FALSE)
357       return NULL;
358   }
359
360   if (hmac)
361     mac_len = silc_hmac_len(hmac);
362
363   /* IV is present for all channel messages, and private messages when
364      static key (pre-shared key) is used. */
365   if (cipher && (!private_message || (private_message && static_key)))
366     iv_len = silc_cipher_get_block_len(cipher);
367
368   if (!message) {
369     newp = message = silc_calloc(1, sizeof(*newp));
370     if (!newp)
371       return NULL;
372   }
373   memset(message, 0, sizeof(*message));
374   message->allocated = (stack || no_allocation ? FALSE : TRUE);
375
376   /* Parse the Message Payload. */
377   if (!no_allocation)
378     ret = silc_buffer_sunformat(stack, &buffer,
379                           SILC_STR_UI_SHORT(&message->flags),
380                           SILC_STR_UI16_NSTRING_ALLOC(&message->data,
381                                                       &message->data_len),
382                           SILC_STR_UI16_NSTRING_ALLOC(&message->pad,
383                                                       &message->pad_len),
384                           SILC_STR_END);
385   else
386     ret = silc_buffer_unformat(&buffer,
387                                SILC_STR_UI_SHORT(&message->flags),
388                                SILC_STR_UI16_NSTRING(&message->data,
389                                                      &message->data_len),
390                                SILC_STR_UI16_NSTRING(&message->pad,
391                                                      &message->pad_len),
392                                SILC_STR_END);
393   if (ret == -1)
394     goto err;
395
396   if ((message->data_len > silc_buffer_len(&buffer) - 6 - mac_len - iv_len) ||
397       (message->pad_len + message->data_len > silc_buffer_len(&buffer) -
398        6 - mac_len - iv_len)) {
399     SILC_LOG_ERROR(("Incorrect Message Payload in packet"));
400     goto err;
401   }
402
403   /* Parse Signed Message Payload if provided */
404   if (message->flags & SILC_MESSAGE_FLAG_SIGNED &&
405       message->data_len + message->pad_len + 6 + mac_len +
406       iv_len < silc_buffer_len(&buffer)) {
407     if (!silc_message_signed_payload_parse(buffer.data + 6 +
408                                            message->data_len +
409                                            message->pad_len,
410                                            silc_buffer_len(&buffer) -
411                                            iv_len - mac_len - 6 -
412                                            message->data_len -
413                                            message->pad_len,
414                                            &message->sig))
415       goto err;
416   }
417
418   /* Parse MAC from the payload */
419   if (mac_len)
420     message->mac = buffer.data + (silc_buffer_len(&buffer) - mac_len);
421
422   return newp;
423
424  err:
425   if (newp)
426     silc_message_payload_free(newp);
427   return NULL;
428 }
429
430
431 /***************************** Payload encoding *****************************/
432
433 /* This function is used to encrypt the Messsage Payload which is
434    the `data' and `data_len'.  This is used internally by the Message
435    Payload encoding routines but application may call this too if needed.
436    The `true_len' is the data length which is used to create MAC out of. */
437
438 SilcBool silc_message_payload_encrypt(unsigned char *data,
439                                       SilcUInt32 data_len,
440                                       SilcUInt32 true_len,
441                                       unsigned char *iv,
442                                       SilcCipher cipher,
443                                       SilcHmac hmac)
444 {
445   /* Encrypt payload of the packet */
446   if (!silc_cipher_encrypt(cipher, data, data, data_len, iv))
447     return FALSE;
448
449   /* Compute the MAC of the encrypted message data */
450   silc_hmac_init(hmac);
451   silc_hmac_update(hmac, data, true_len);
452   silc_hmac_final(hmac, data + true_len, NULL);
453
454   return TRUE;
455 }
456
457 /* Encrypt message payload */
458
459 static int silc_message_payload_encode_encrypt(SilcBuffer buffer,
460                                                void *value, void *context)
461 {
462   SilcMessageEncode *e = context;
463   SilcUInt32 mac_len;
464
465   if (!e->cipher || !e->hmac)
466     return 0;
467
468   mac_len = silc_hmac_len(e->hmac);
469   if (!silc_buffer_enlarge(buffer, mac_len))
470     return -1;
471
472   if (!silc_message_payload_encrypt(buffer->head,
473                                     e->payload_len,
474                                     silc_buffer_headlen(buffer),
475                                     e->iv, e->cipher, e->hmac))
476     return -1;
477
478   return mac_len;
479 }
480
481 /* Compute message signature */
482
483 static int silc_message_payload_encode_sig(SilcBuffer buffer,
484                                            void *value, void *context)
485 {
486   SilcMessageEncode *e = context;
487   SilcBuffer sig;
488   int len;
489
490   if (!(e->flags & SILC_MESSAGE_FLAG_SIGNED))
491     return 0;
492
493   sig = silc_message_signed_payload_encode(buffer->head,
494                                            silc_buffer_headlen(buffer),
495                                            e->public_key, e->private_key,
496                                            e->hash);
497   if (!sig)
498     return -1;
499
500   len = silc_buffer_format(buffer,
501                            SILC_STR_DATA(silc_buffer_data(sig),
502                                          silc_buffer_len(sig)),
503                            SILC_STR_END);
504   if (len < 0) {
505     silc_buffer_free(sig);
506     return -1;
507   }
508
509   silc_buffer_free(sig);
510   return len;
511 }
512
513 /* Encodes Message Payload into a buffer and returns it. */
514
515 SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
516                                        const unsigned char *data,
517                                        SilcUInt32 data_len,
518                                        SilcBool generate_iv,
519                                        SilcBool private_message,
520                                        SilcCipher cipher,
521                                        SilcHmac hmac,
522                                        SilcRng rng,
523                                        SilcPublicKey public_key,
524                                        SilcPrivateKey private_key,
525                                        SilcHash hash,
526                                        SilcBuffer buffer)
527 {
528   SilcUInt32 pad_len = 0, mac_len = 0, iv_len = 0;
529   unsigned char pad[16], iv[SILC_CIPHER_MAX_IV_SIZE];
530   SilcBuffer buf = NULL;
531   SilcMessageEncode e;
532   int i;
533
534   SILC_LOG_DEBUG(("Encoding Message Payload"));
535
536   if (!data_len)
537     return NULL;
538   if (!private_message && (!cipher || !hmac))
539     return NULL;
540
541   if (!buffer) {
542     buf = buffer = silc_buffer_alloc(0);
543     if (!buf)
544       return NULL;
545   }
546   silc_buffer_reset(buffer);
547
548   /* For channel messages IV is always generated */
549   if (!private_message && !generate_iv)
550     generate_iv = TRUE;
551
552   /* Generate IV */
553   if (cipher && generate_iv) {
554     iv_len = silc_cipher_get_block_len(cipher);
555     if (rng) {
556       for (i = 0; i < iv_len; i++) iv[i] = silc_rng_get_byte_fast(rng);
557     } else {
558       for (i = 0; i < iv_len; i++) iv[i] = silc_rng_global_get_byte_fast();
559     }
560   }
561
562   if (hmac)
563     mac_len = silc_hmac_len(hmac);
564   data_len = silc_message_payload_datalen(data_len, mac_len + iv_len, flags,
565                                           public_key, private_key);
566
567   /* Calculate length of padding. IV is not included into the calculation
568      since it is not encrypted. */
569   pad_len = SILC_MESSAGE_PAD(6 + data_len);
570
571   /* Generate padding */
572   if (cipher) {
573     if (rng) {
574       for (i = 0; i < pad_len; i++) pad[i] = silc_rng_get_byte_fast(rng);
575     } else {
576       for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte_fast();
577     }
578   }
579
580   e.flags = flags;
581   e.public_key = public_key;
582   e.private_key = private_key;
583   e.hash = hash;
584   e.cipher = cipher;
585   e.hmac = hmac;
586   e.iv = iv_len ? iv : NULL;
587   e.payload_len = 6 + data_len + pad_len;
588
589   /* Encode the Message Payload */
590   if (silc_buffer_format(buffer,
591                          SILC_STR_UI_SHORT(flags),
592                          SILC_STR_UI_SHORT(data_len),
593                          SILC_STR_DATA(data, data_len),
594                          SILC_STR_UI_SHORT(pad_len),
595                          SILC_STR_DATA(pad, pad_len),
596                          SILC_STR_FUNC(silc_message_payload_encode_sig,
597                                        NULL, &e),
598                          SILC_STR_DATA(iv, iv_len),
599                          SILC_STR_FUNC(silc_message_payload_encode_encrypt,
600                                        NULL, &e),
601                          SILC_STR_END) < 0) {
602     silc_buffer_free(buf);
603     return NULL;
604   }
605
606   return buffer;
607 }
608
609 /* Free's Message Payload */
610
611 void silc_message_payload_free(SilcMessagePayload payload)
612 {
613   if (payload->data) {
614     memset(payload->data, 0, payload->data_len);
615     if (payload->allocated)
616       silc_free(payload->data);
617   }
618   if (payload->allocated) {
619     silc_free(payload->pad);
620     silc_free(payload);
621   }
622   silc_message_signed_payload_free(&payload->sig);
623 }
624
625 /* Return flags */
626
627 SilcMessageFlags silc_message_get_flags(SilcMessagePayload payload)
628 {
629   return payload->flags;
630 }
631
632 /* Return data */
633
634 unsigned char *silc_message_get_data(SilcMessagePayload payload,
635                                      SilcUInt32 *data_len)
636 {
637   if (data_len)
638     *data_len = payload->data_len;
639   return payload->data;
640 }
641
642 /* Return MAC. The caller knows the length of the MAC */
643
644 unsigned char *silc_message_get_mac(SilcMessagePayload payload)
645 {
646   return payload->mac;
647 }
648
649 /* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
650
651 int silc_message_signed_verify(SilcMessagePayload message,
652                                SilcPublicKey remote_public_key,
653                                SilcHash hash)
654 {
655   int ret = SILC_AUTH_FAILED;
656   SilcBuffer sign, tmp;
657   SilcMessageSignedPayload sig = &message->sig;
658
659   if (!(message->flags & SILC_MESSAGE_FLAG_SIGNED) ||
660       !sig->sign_len || !remote_public_key || !hash)
661     return ret;
662
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),
671                      SILC_STR_END);
672   sign = silc_message_signed_encode_data(tmp->data, silc_buffer_len(tmp),
673                                          sig->pk_data, sig->pk_len,
674                                          sig->pk_type);
675   silc_buffer_clear(tmp);
676   silc_buffer_free(tmp);
677
678   if (!sign)
679     return ret;
680
681   /* Verify the authentication data */
682   if (!silc_pkcs_verify(remote_public_key, sig->sign_data, sig->sign_len,
683                         silc_buffer_data(sign), silc_buffer_len(sign), hash)) {
684     silc_buffer_clear(sign);
685     silc_buffer_free(sign);
686     SILC_LOG_DEBUG(("Signature verification failed"));
687     return ret;
688   }
689
690   ret = SILC_AUTH_OK;
691
692   silc_buffer_clear(sign);
693   silc_buffer_free(sign);
694
695   SILC_LOG_DEBUG(("Signature verification successful"));
696
697   return ret;
698 }
699
700 /* Return the public key from the payload */
701
702 SilcPublicKey
703 silc_message_signed_get_public_key(SilcMessagePayload payload,
704                                    const unsigned char **pk_data,
705                                    SilcUInt32 *pk_data_len)
706 {
707   SilcPublicKey pk;
708   SilcMessageSignedPayload sig = &payload->sig;
709
710   if (!sig->pk_data)
711     return NULL;
712
713   if (!silc_pkcs_public_key_alloc(sig->pk_type, sig->pk_data,
714                                   sig->pk_len, &pk))
715     return NULL;
716
717   if (pk_data)
718     *pk_data = sig->pk_data;
719   if (pk_data_len)
720     *pk_data_len = sig->pk_len;
721
722   return pk;
723 }