Fixed the message payload decryption to understand any length
[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, iv_len = 0;
71   SilcUInt16 len, totlen;
72   unsigned char mac[32], *ivp, *dec;
73   
74   mac_len = silc_hmac_len(hmac);
75
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);
80
81   if (data_len < mac_len)
82     return FALSE;
83
84   if (check_mac) {
85     /* Check the MAC of the message */
86     SILC_LOG_DEBUG(("Checking message MAC"));
87     silc_hmac_init(hmac);
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"));
92       return FALSE;
93     }
94     SILC_LOG_DEBUG(("MAC is Ok"));
95   }
96
97   /* Get pointer to the IV */
98   ivp = (iv_len ? data + (data_len - iv_len - mac_len) :
99          silc_cipher_get_iv(cipher));
100
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);
108
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. */
112
113   totlen = 2;
114   SILC_GET16_MSB(len, dec + totlen);
115   totlen += 2 + len;
116   if (totlen + iv_len + mac_len + 2 > data_len) {
117     memset(dec, 0, data_len);
118     silc_free(dec);
119     return FALSE;
120   }
121   SILC_GET16_MSB(len, dec + totlen);
122   totlen += 2 + len;
123   if (totlen + iv_len + mac_len > data_len) {
124     memset(dec, 0, data_len);
125     silc_free(dec);
126     return FALSE;
127   }
128
129   memcpy(data, dec, totlen);
130   memset(dec, 0, data_len);
131   silc_free(dec);
132
133   return TRUE;
134 }
135
136 /* Parses Message Payload returning new payload structure.  This also
137    decrypts it and checks the MAC. */
138
139 SilcMessagePayload 
140 silc_message_payload_parse(unsigned char *payload,
141                            SilcUInt32 payload_len,
142                            bool private_message,
143                            bool static_key,
144                            SilcCipher cipher,
145                            SilcHmac hmac)
146 {
147   SilcBufferStruct buffer;
148   SilcMessagePayload newp;
149   int ret;
150   SilcUInt32 mac_len = 0, iv_len = 0;
151
152   SILC_LOG_DEBUG(("Parsing Message Payload"));
153
154   silc_buffer_set(&buffer, payload, payload_len);
155
156   /* Decrypt the payload */
157   if (cipher) {
158     ret = silc_message_payload_decrypt(buffer.data, buffer.len,
159                                        private_message, static_key,
160                                        cipher, hmac, TRUE);
161     if (ret == FALSE)
162       return NULL;
163   }
164
165   if (hmac)
166     mac_len = silc_hmac_len(hmac);
167
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);
172
173   newp = silc_calloc(1, sizeof(*newp));
174   if (!newp)
175     return NULL;
176
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, 
181                                                          &newp->data_len),
182                              SILC_STR_UI16_NSTRING_ALLOC(&newp->pad, 
183                                                          &newp->pad_len),
184                              SILC_STR_END);
185   if (ret == -1)
186     goto err;
187
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"));
191     goto err;
192   }
193
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) {
197     newp->sig =
198       silc_message_signed_payload_parse(buffer.data + 6 + newp->data_len +
199                                         newp->pad_len,
200                                         buffer.len - iv_len - mac_len);
201   }
202
203   /* Parse IV and MAC from the payload */
204   if (iv_len) {
205     newp->iv = buffer.data + (buffer.len - iv_len - mac_len);
206     newp->iv_len = iv_len;
207   }
208   if (mac_len)
209     newp->mac = buffer.data + (buffer.len - mac_len);
210
211   return newp;
212
213  err:
214   silc_message_payload_free(newp);
215   return NULL;
216 }
217
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. */
222
223 bool silc_message_payload_encrypt(unsigned char *data,
224                                   SilcUInt32 data_len,
225                                   SilcUInt32 true_len,
226                                   unsigned char *iv,
227                                   SilcUInt32 iv_len,
228                                   SilcCipher cipher,
229                                   SilcHmac hmac)
230 {
231   unsigned char mac[32];
232   SilcUInt32 mac_len;
233   SilcBufferStruct buf;
234
235   /* Encrypt payload of the packet. If the IV is added to packet do
236      not encrypt that. */
237   silc_cipher_encrypt(cipher, data, data, data_len, iv_len ? iv : NULL);
238
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);
243
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);
248
249   return TRUE;
250 }
251
252 /* Encodes Message Payload into a buffer and returns it. */
253
254 SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
255                                        const unsigned char *data,
256                                        SilcUInt32 data_len,
257                                        bool generate_iv,
258                                        bool private_message,
259                                        SilcCipher cipher,
260                                        SilcHmac hmac,
261                                        SilcRng rng,
262                                        SilcPublicKey public_key,
263                                        SilcPrivateKey private_key,
264                                        SilcHash hash)
265 {
266   int i;
267   SilcBuffer buffer;
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;
271
272   SILC_LOG_DEBUG(("Encoding Message Payload"));
273
274   if (!data_len)
275     return NULL;
276
277   /* For channel messages IV is always generated */
278   if (!private_message && !generate_iv)
279     generate_iv = TRUE;
280
281   /* Generate IV */
282   if (cipher && generate_iv) {
283     iv_len = silc_cipher_get_block_len(cipher);
284     if (rng) {
285       for (i = 0; i < iv_len; i++) iv[i] = silc_rng_get_byte_fast(rng);
286     } else {
287       for (i = 0; i < iv_len; i++) iv[i] = silc_rng_global_get_byte_fast();
288     }
289   }
290
291   if (hmac)
292     mac_len = silc_hmac_len(hmac);
293   data_len = SILC_MESSAGE_DATALEN(data_len, mac_len + iv_len);
294
295   /* Calculate length of padding. IV is not included into the calculation
296      since it is not encrypted. */
297   len = 6 + data_len;
298   pad_len = SILC_MESSAGE_PAD(len);
299
300   /* Allocate payload buffer */
301   len += pad_len + iv_len + mac_len;
302   buffer = silc_buffer_alloc(len);
303   if (!buffer)
304     return NULL;
305
306   /* Generate padding */
307   if (cipher) {
308     if (rng) {
309       for (i = 0; i < pad_len; i++) pad[i] = silc_rng_get_byte_fast(rng);
310     } else {
311       for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte_fast();
312     }
313   }
314
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),
323                      SILC_STR_END);
324
325   memset(pad, 0, sizeof(pad));
326
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);
331     if (sig) {
332       buffer = silc_buffer_realloc(buffer, buffer->truelen + sig->len);
333       if (buffer) {
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);
338       }
339     }
340   }
341
342   /* Put IV */
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),
347                      SILC_STR_END);
348   silc_buffer_push(buffer, 6 + data_len + pad_len + (sig ? sig->len : 0));
349   
350   SILC_LOG_HEXDUMP(("foo"), buffer->data, buffer->len);
351   
352   /* Now encrypt the Message Payload and compute MAC */
353   if (cipher) {
354     if (!silc_message_payload_encrypt(buffer->data,
355                                       buffer->len - iv_len -
356                                       (sig ? sig->len : 0),
357                                       buffer->len, iv, iv_len,
358                                       cipher, hmac)) {
359       silc_buffer_free(buffer);
360       silc_buffer_free(sig);
361       return NULL;
362     }
363   }
364   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer) - buffer->len);
365
366   silc_buffer_free(sig);
367   return buffer;
368 }
369
370 /* Free's Message Payload */
371
372 void silc_message_payload_free(SilcMessagePayload payload)
373 {
374   if (payload->data) {
375     memset(payload->data, 0, payload->data_len);
376     silc_free(payload->data);
377   }
378   if (payload->sig)
379     silc_message_signed_payload_free(payload->sig);
380   silc_free(payload->pad);
381   silc_free(payload);
382 }
383
384 /* Return flags */
385
386 SilcMessageFlags silc_message_get_flags(SilcMessagePayload payload)
387 {
388   return payload->flags;
389 }
390
391 /* Return data */
392
393 unsigned char *silc_message_get_data(SilcMessagePayload payload,
394                                      SilcUInt32 *data_len)
395 {
396   if (data_len)
397     *data_len = payload->data_len;
398   return payload->data;
399 }
400
401 /* Return MAC. The caller knows the length of the MAC */
402
403 unsigned char *silc_message_get_mac(SilcMessagePayload payload)
404 {
405   return payload->mac;
406 }
407
408 /* Return IV. The caller knows the length of the IV */
409
410 unsigned char *silc_message_get_iv(SilcMessagePayload payload)
411 {
412   return payload->iv;
413 }
414
415 /* Return signature of the message */
416
417 const SilcMessageSignedPayload
418 silc_message_get_signature(SilcMessagePayload payload)
419 {
420   return (const SilcMessageSignedPayload)payload->sig;
421 }
422
423 /******************************************************************************
424
425                      SILC_MESSAGE_FLAG_SIGNED Payload
426
427 ******************************************************************************/
428
429 /* The SILC_MESSAGE_FLAG_SIGNED Payload */
430 struct SilcMessageSignedPayloadStruct {
431   SilcUInt16 pk_len;
432   SilcUInt16 pk_type;
433   SilcUInt16 sign_len;
434   unsigned char *pk_data;
435   unsigned char *sign_data;
436 };
437
438 /* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */
439
440 static SilcBuffer
441 silc_message_signed_encode_data(const unsigned char *message_payload,
442                                 SilcUInt32 message_payload_len,
443                                 unsigned char *pk,
444                                 SilcUInt32 pk_len, SilcUInt32 pk_type)
445 {
446   SilcBuffer sign;
447
448   sign = silc_buffer_alloc_size(message_payload_len + 4 + pk_len);
449   if (!sign)
450     return NULL;
451
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),
457                      SILC_STR_END);
458
459   if (pk && pk_len) {
460     silc_buffer_pull(sign, message_payload_len + 4);
461     silc_buffer_format(sign,
462                        SILC_STR_UI_XNSTRING(pk, pk_len),
463                        SILC_STR_END);
464     silc_buffer_push(sign, message_payload_len + 4);
465   }
466
467   return sign;
468 }
469
470 /* Parses the SILC_MESSAGE_FLAG_SIGNED Payload */
471
472 SilcMessageSignedPayload
473 silc_message_signed_payload_parse(const unsigned char *data,
474                                   SilcUInt32 data_len)
475 {
476   SilcMessageSignedPayload sig;
477   SilcBufferStruct buffer;
478   int ret;
479
480   SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload"));
481
482   SILC_LOG_HEXDUMP(("sig payload"), (unsigned char *)data, data_len);
483
484   silc_buffer_set(&buffer, (unsigned char *)data, data_len);
485   sig = silc_calloc(1, sizeof(*sig));
486   if (!sig)
487     return NULL;
488
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),
493                              SILC_STR_END);
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 "
497                     "Payload"));
498     return NULL;
499   }
500
501   silc_buffer_pull(&buffer, 4);
502   ret = silc_buffer_unformat(&buffer,
503                              SILC_STR_UI_XNSTRING_ALLOC(&sig->pk_data,
504                                                         sig->pk_len),
505                              SILC_STR_UI16_NSTRING_ALLOC(&sig->sign_data,
506                                                          &sig->sign_len),
507                              SILC_STR_END);
508   if (ret == -1) {
509     silc_message_signed_payload_free(sig);
510     SILC_LOG_DEBUG(("Malformed SILC_MESSAGE_FLAG_SIGNED Payload"));
511     return NULL;
512   }
513   silc_buffer_push(&buffer, 4);
514
515   /* Signature must be provided */
516   if (sig->sign_len < 1)  {
517     SILC_LOG_DEBUG(("Malformed signature in SILC_MESSAGE_SIGNED_PAYLOAD "
518                     "Payload"));
519     silc_message_signed_payload_free(sig);
520     return NULL;
521   }
522
523   return sig;
524 }
525
526 /* Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the digital
527    signature. */
528
529 SilcBuffer
530 silc_message_signed_payload_encode(const unsigned char *message_payload,
531                                    SilcUInt32 message_payload_len,
532                                    SilcPublicKey public_key,
533                                    SilcPrivateKey private_key,
534                                    SilcHash hash)
535 {
536   SilcBuffer buffer, sign;
537   SilcPKCS pkcs;
538   unsigned char auth_data[2048];
539   SilcUInt32 auth_len;
540   unsigned char *pk = NULL;
541   SilcUInt32 pk_len = 0;
542   SilcUInt16 pk_type;
543
544   if (!message_payload || !message_payload_len || !private_key || !hash)
545     return NULL;
546   
547   if (public_key)
548     pk = silc_pkcs_public_key_encode(public_key, &pk_len);
549
550   /* Now we support only SILC style public key */
551   pk_type = SILC_SKE_PK_TYPE_SILC;
552
553   /* Encode the data to be signed */
554   sign = silc_message_signed_encode_data(message_payload,
555                                          message_payload_len,
556                                          pk, pk_len, pk_type);
557   if (!sign) {
558     silc_free(pk);
559     return NULL;
560   }
561
562   /* Sign the buffer */
563
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);
569     silc_free(pk);
570     return NULL;
571   }
572   silc_pkcs_private_key_set(pkcs, private_key);
573
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,
577                                 &auth_len)) {
578     SILC_LOG_ERROR(("Could not compute signature"));
579     silc_buffer_clear(sign);
580     silc_buffer_free(sign);
581     silc_pkcs_free(pkcs);
582     silc_free(pk);
583     return NULL;
584   }
585
586   /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */
587
588   buffer = silc_buffer_alloc_size(4 + pk_len + 2 + auth_len);
589   if (!buffer) {
590     silc_buffer_clear(sign);
591     silc_buffer_free(sign);
592     silc_pkcs_free(pkcs);
593     memset(auth_data, 0, sizeof(auth_data));
594     silc_free(pk);
595     return NULL;
596   }
597
598   silc_buffer_format(buffer,
599                      SILC_STR_UI_SHORT(pk_len),
600                      SILC_STR_UI_SHORT(pk_type),
601                      SILC_STR_END);
602
603   if (pk_len && pk) {
604     silc_buffer_pull(buffer, 4);
605     silc_buffer_format(buffer,
606                        SILC_STR_UI_XNSTRING(pk, pk_len),
607                        SILC_STR_END);
608     silc_buffer_push(buffer, 4);
609   }
610
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),
615                      SILC_STR_END);
616   silc_buffer_push(buffer, 4 + pk_len);
617
618   SILC_LOG_HEXDUMP(("sig payload"), buffer->data, buffer->len);
619
620   memset(auth_data, 0, sizeof(auth_data));
621   silc_pkcs_free(pkcs);
622   silc_buffer_clear(sign);
623   silc_buffer_free(sign);
624   silc_free(pk);
625
626   return buffer;
627 }
628
629 /* Free the payload */
630
631 void silc_message_signed_payload_free(SilcMessageSignedPayload sig)
632 {
633   memset(sig->sign_data, 0, sig->sign_len);
634   silc_free(sig->sign_data);
635   silc_free(sig->pk_data);
636   silc_free(sig);
637 }
638
639 /* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
640
641 int silc_message_signed_verify(SilcMessageSignedPayload sig,
642                                SilcMessagePayload message,
643                                SilcPublicKey remote_public_key,
644                                SilcHash hash)
645 {
646   int ret = SILC_AUTH_FAILED;
647   SilcBuffer sign;
648   SilcPKCS pkcs;
649   SilcBuffer tmp;
650   
651   if (!sig || !remote_public_key || !hash)
652     return ret;
653
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),
662                      SILC_STR_END);
663   sign = silc_message_signed_encode_data(tmp->data, tmp->len,
664                                          sig->pk_data, sig->pk_len,
665                                          sig->pk_type);
666   silc_buffer_clear(tmp);
667   silc_buffer_free(tmp);
668   
669   if (!sign)
670     return ret;
671   
672   /* Allocate PKCS object */
673   if (!silc_pkcs_alloc(remote_public_key->name, &pkcs)) {
674     silc_buffer_clear(sign);
675     silc_buffer_free(sign);
676     return ret;
677   }
678   silc_pkcs_public_key_set(pkcs, remote_public_key);
679
680   /* Verify the authentication data */
681   if (!silc_pkcs_verify_with_hash(pkcs, hash, sig->sign_data,
682                                   sig->sign_len,
683                                   sign->data, sign->len)) {
684
685     silc_buffer_clear(sign);
686     silc_buffer_free(sign);
687     silc_pkcs_free(pkcs);
688     SILC_LOG_DEBUG(("Signature verification failed"));
689     return ret;
690   }
691
692   ret = SILC_AUTH_OK;
693
694   silc_buffer_clear(sign);
695   silc_buffer_free(sign);
696   silc_pkcs_free(pkcs);
697
698   SILC_LOG_DEBUG(("Signature verification successful"));
699
700   return ret;
701 }
702
703 /* Return the public key from the payload */
704
705 SilcPublicKey
706 silc_message_signed_get_public_key(SilcMessageSignedPayload sig)
707 {
708   SilcPublicKey pk;
709
710   if (!sig->pk_data || !silc_pkcs_public_key_decode(sig->pk_data,
711                                                     sig->pk_len, &pk))
712     return NULL;
713
714   return pk;
715 }