Merged from silc_1_0_branch.
[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, block_len;
71   SilcUInt16 len, totlen, dlen;
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   /* Decrypt the entire buffer into allocated decryption buffer, since we
98      do not reliably know its encrypted length (it may include unencrypted
99      data at the end). */
100
101   /* Get pointer to the IV */
102   ivp = (iv_len ? data + (data_len - iv_len - mac_len) :
103          silc_cipher_get_iv(cipher));
104
105   /* Allocate buffer for decryption.  Since there might be unencrypted
106      data at the end, it might not be multiple by block size, make it so. */
107   block_len = silc_cipher_get_block_len(cipher);
108   dlen = data_len - iv_len - mac_len;
109   if (dlen & (block_len - 1))
110     dlen += SILC_MESSAGE_PAD(dlen);
111   if (dlen > data_len - iv_len - mac_len)
112     dlen -= block_len;
113   dec = silc_malloc(dlen);
114
115   /* Decrypt */
116   silc_cipher_decrypt(cipher, data, dec, dlen, ivp);
117
118   /* Now verify the true length of the payload and copy the decrypted
119      part over the original data.  First get data length, and then padding
120      length from the decrypted data.  Then, copy over the original data. */
121
122   totlen = 2;
123   SILC_GET16_MSB(len, dec + totlen);
124   totlen += 2 + len;
125   if (totlen + iv_len + mac_len + 2 > data_len) {
126     memset(dec, 0, dlen);
127     silc_free(dec);
128     return FALSE;
129   }
130   SILC_GET16_MSB(len, dec + totlen);
131   totlen += 2 + len;
132   if (totlen + iv_len + mac_len > data_len) {
133     memset(dec, 0, dlen);
134     silc_free(dec);
135     return FALSE;
136   }
137
138   memcpy(data, dec, totlen);
139   memset(dec, 0, dlen);
140   silc_free(dec);
141
142   return TRUE;
143 }
144
145 /* Parses Message Payload returning new payload structure.  This also
146    decrypts it and checks the MAC. */
147
148 SilcMessagePayload 
149 silc_message_payload_parse(unsigned char *payload,
150                            SilcUInt32 payload_len,
151                            bool private_message,
152                            bool static_key,
153                            SilcCipher cipher,
154                            SilcHmac hmac)
155 {
156   SilcBufferStruct buffer;
157   SilcMessagePayload newp;
158   int ret;
159   SilcUInt32 mac_len = 0, iv_len = 0;
160
161   SILC_LOG_DEBUG(("Parsing Message Payload"));
162
163   silc_buffer_set(&buffer, payload, payload_len);
164
165   /* Decrypt the payload */
166   if (cipher) {
167     ret = silc_message_payload_decrypt(buffer.data, buffer.len,
168                                        private_message, static_key,
169                                        cipher, hmac, TRUE);
170     if (ret == FALSE)
171       return NULL;
172   }
173
174   if (hmac)
175     mac_len = silc_hmac_len(hmac);
176
177   /* IV is present for all channel messages, and private messages when 
178      static key (pre-shared key) is used. */
179   if (cipher && (!private_message || (private_message && static_key)))
180     iv_len = silc_cipher_get_block_len(cipher);
181
182   newp = silc_calloc(1, sizeof(*newp));
183   if (!newp)
184     return NULL;
185
186   /* Parse the Message Payload. */
187   ret = silc_buffer_unformat(&buffer,
188                              SILC_STR_UI_SHORT(&newp->flags),
189                              SILC_STR_UI16_NSTRING_ALLOC(&newp->data, 
190                                                          &newp->data_len),
191                              SILC_STR_UI16_NSTRING_ALLOC(&newp->pad, 
192                                                          &newp->pad_len),
193                              SILC_STR_END);
194   if (ret == -1)
195     goto err;
196
197   if ((newp->data_len > buffer.len - 6 - mac_len - iv_len) ||
198       (newp->pad_len + newp->data_len > buffer.len - 6 - mac_len - iv_len)) {
199     SILC_LOG_ERROR(("Incorrect Message Payload in packet"));
200     goto err;
201   }
202
203   /* Parse Signed Message Payload if provided */
204   if (newp->flags & SILC_MESSAGE_FLAG_SIGNED &&
205       newp->data_len + newp->pad_len + 6 + mac_len + iv_len < buffer.len) {
206     newp->sig =
207       silc_message_signed_payload_parse(buffer.data + 6 + newp->data_len +
208                                         newp->pad_len,
209                                         buffer.len - iv_len - mac_len);
210   }
211
212   /* Parse IV and MAC from the payload */
213   if (iv_len) {
214     newp->iv = buffer.data + (buffer.len - iv_len - mac_len);
215     newp->iv_len = iv_len;
216   }
217   if (mac_len)
218     newp->mac = buffer.data + (buffer.len - mac_len);
219
220   return newp;
221
222  err:
223   silc_message_payload_free(newp);
224   return NULL;
225 }
226
227 /* This function is used to encrypt the Messsage Payload which is
228    the `data' and `data_len'.  This is used internally by the Message
229    Payload encoding routines but application may call this too if needed. 
230    The `true_len' is the data length which is used to create MAC out of. */
231
232 bool silc_message_payload_encrypt(unsigned char *data,
233                                   SilcUInt32 data_len,
234                                   SilcUInt32 true_len,
235                                   unsigned char *iv,
236                                   SilcUInt32 iv_len,
237                                   SilcCipher cipher,
238                                   SilcHmac hmac)
239 {
240   unsigned char mac[32];
241   SilcUInt32 mac_len;
242   SilcBufferStruct buf;
243
244   /* Encrypt payload of the packet. If the IV is added to packet do
245      not encrypt that. */
246   silc_cipher_encrypt(cipher, data, data, data_len, iv_len ? iv : NULL);
247
248   /* Compute the MAC of the encrypted message data */
249   silc_hmac_init(hmac);
250   silc_hmac_update(hmac, data, true_len);
251   silc_hmac_final(hmac, mac, &mac_len);
252
253   /* Put rest of the data to the payload */
254   silc_buffer_set(&buf, data, true_len + mac_len);
255   silc_buffer_pull(&buf, true_len);
256   silc_buffer_put(&buf, mac, mac_len);
257
258   return TRUE;
259 }
260
261 /* Encodes Message Payload into a buffer and returns it. */
262
263 SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
264                                        const unsigned char *data,
265                                        SilcUInt32 data_len,
266                                        bool generate_iv,
267                                        bool private_message,
268                                        SilcCipher cipher,
269                                        SilcHmac hmac,
270                                        SilcRng rng,
271                                        SilcPublicKey public_key,
272                                        SilcPrivateKey private_key,
273                                        SilcHash hash)
274 {
275   int i;
276   SilcBuffer buffer;
277   SilcUInt32 len, pad_len = 0, mac_len = 0, iv_len = 0;
278   unsigned char pad[16], iv[SILC_CIPHER_MAX_IV_SIZE];
279   SilcBuffer sig = NULL;
280
281   SILC_LOG_DEBUG(("Encoding Message Payload"));
282
283   if (!data_len)
284     return NULL;
285
286   /* For channel messages IV is always generated */
287   if (!private_message && !generate_iv)
288     generate_iv = TRUE;
289
290   /* Generate IV */
291   if (cipher && generate_iv) {
292     iv_len = silc_cipher_get_block_len(cipher);
293     if (rng) {
294       for (i = 0; i < iv_len; i++) iv[i] = silc_rng_get_byte_fast(rng);
295     } else {
296       for (i = 0; i < iv_len; i++) iv[i] = silc_rng_global_get_byte_fast();
297     }
298   }
299
300   if (hmac)
301     mac_len = silc_hmac_len(hmac);
302   data_len = SILC_MESSAGE_DATALEN(data_len, mac_len + iv_len);
303
304   /* Calculate length of padding. IV is not included into the calculation
305      since it is not encrypted. */
306   len = 6 + data_len;
307   pad_len = SILC_MESSAGE_PAD(len);
308
309   /* Allocate payload buffer */
310   len += pad_len + iv_len + mac_len;
311   buffer = silc_buffer_alloc(len);
312   if (!buffer)
313     return NULL;
314
315   /* Generate padding */
316   if (cipher) {
317     if (rng) {
318       for (i = 0; i < pad_len; i++) pad[i] = silc_rng_get_byte_fast(rng);
319     } else {
320       for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte_fast();
321     }
322   }
323
324   /* Encode the Message Payload */
325   silc_buffer_pull_tail(buffer, 6 + data_len + pad_len);
326   silc_buffer_format(buffer, 
327                      SILC_STR_UI_SHORT(flags),
328                      SILC_STR_UI_SHORT(data_len),
329                      SILC_STR_UI_XNSTRING(data, data_len),
330                      SILC_STR_UI_SHORT(pad_len),
331                      SILC_STR_UI_XNSTRING(pad, pad_len),
332                      SILC_STR_END);
333
334   memset(pad, 0, sizeof(pad));
335
336   /* Sign the message if wanted */
337   if (flags & SILC_MESSAGE_FLAG_SIGNED && private_key && hash) {
338     sig = silc_message_signed_payload_encode(buffer->data, buffer->len,
339                                              public_key, private_key, hash);
340     if (sig) {
341       buffer = silc_buffer_realloc(buffer, buffer->truelen + sig->len);
342       if (buffer) {
343         silc_buffer_pull(buffer, 6 + data_len + pad_len);
344         silc_buffer_pull_tail(buffer, sig->len);
345         silc_buffer_put(buffer, sig->data, sig->len);
346         silc_buffer_push(buffer, 6 + data_len + pad_len);
347       }
348     }
349   }
350
351   /* Put IV */
352   silc_buffer_pull(buffer, 6 + data_len + pad_len + (sig ? sig->len : 0));
353   silc_buffer_pull_tail(buffer, iv_len);
354   silc_buffer_format(buffer, 
355                      SILC_STR_UI_XNSTRING(iv, iv_len),
356                      SILC_STR_END);
357   silc_buffer_push(buffer, 6 + data_len + pad_len + (sig ? sig->len : 0));
358   
359   SILC_LOG_HEXDUMP(("foo"), buffer->data, buffer->len);
360   
361   /* Now encrypt the Message Payload and compute MAC */
362   if (cipher) {
363     if (!silc_message_payload_encrypt(buffer->data,
364                                       buffer->len - iv_len -
365                                       (sig ? sig->len : 0),
366                                       buffer->len, iv, iv_len,
367                                       cipher, hmac)) {
368       silc_buffer_free(buffer);
369       silc_buffer_free(sig);
370       return NULL;
371     }
372   }
373   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer) - buffer->len);
374
375   silc_buffer_free(sig);
376   return buffer;
377 }
378
379 /* Free's Message Payload */
380
381 void silc_message_payload_free(SilcMessagePayload payload)
382 {
383   if (payload->data) {
384     memset(payload->data, 0, payload->data_len);
385     silc_free(payload->data);
386   }
387   if (payload->sig)
388     silc_message_signed_payload_free(payload->sig);
389   silc_free(payload->pad);
390   silc_free(payload);
391 }
392
393 /* Return flags */
394
395 SilcMessageFlags silc_message_get_flags(SilcMessagePayload payload)
396 {
397   return payload->flags;
398 }
399
400 /* Return data */
401
402 unsigned char *silc_message_get_data(SilcMessagePayload payload,
403                                      SilcUInt32 *data_len)
404 {
405   if (data_len)
406     *data_len = payload->data_len;
407   return payload->data;
408 }
409
410 /* Return MAC. The caller knows the length of the MAC */
411
412 unsigned char *silc_message_get_mac(SilcMessagePayload payload)
413 {
414   return payload->mac;
415 }
416
417 /* Return IV. The caller knows the length of the IV */
418
419 unsigned char *silc_message_get_iv(SilcMessagePayload payload)
420 {
421   return payload->iv;
422 }
423
424 /* Return signature of the message */
425
426 const SilcMessageSignedPayload
427 silc_message_get_signature(SilcMessagePayload payload)
428 {
429   return (const SilcMessageSignedPayload)payload->sig;
430 }
431
432 /******************************************************************************
433
434                      SILC_MESSAGE_FLAG_SIGNED Payload
435
436 ******************************************************************************/
437
438 /* The SILC_MESSAGE_FLAG_SIGNED Payload */
439 struct SilcMessageSignedPayloadStruct {
440   SilcUInt16 pk_len;
441   SilcUInt16 pk_type;
442   SilcUInt16 sign_len;
443   unsigned char *pk_data;
444   unsigned char *sign_data;
445 };
446
447 /* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */
448
449 static SilcBuffer
450 silc_message_signed_encode_data(const unsigned char *message_payload,
451                                 SilcUInt32 message_payload_len,
452                                 unsigned char *pk,
453                                 SilcUInt32 pk_len, SilcUInt32 pk_type)
454 {
455   SilcBuffer sign;
456
457   sign = silc_buffer_alloc_size(message_payload_len + 4 + pk_len);
458   if (!sign)
459     return NULL;
460
461   silc_buffer_format(sign,
462                      SILC_STR_UI_XNSTRING(message_payload,
463                                           message_payload_len),
464                      SILC_STR_UI_SHORT(pk_len),
465                      SILC_STR_UI_SHORT(pk_type),
466                      SILC_STR_END);
467
468   if (pk && pk_len) {
469     silc_buffer_pull(sign, message_payload_len + 4);
470     silc_buffer_format(sign,
471                        SILC_STR_UI_XNSTRING(pk, pk_len),
472                        SILC_STR_END);
473     silc_buffer_push(sign, message_payload_len + 4);
474   }
475
476   return sign;
477 }
478
479 /* Parses the SILC_MESSAGE_FLAG_SIGNED Payload */
480
481 SilcMessageSignedPayload
482 silc_message_signed_payload_parse(const unsigned char *data,
483                                   SilcUInt32 data_len)
484 {
485   SilcMessageSignedPayload sig;
486   SilcBufferStruct buffer;
487   int ret;
488
489   SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload"));
490
491   SILC_LOG_HEXDUMP(("sig payload"), (unsigned char *)data, data_len);
492
493   silc_buffer_set(&buffer, (unsigned char *)data, data_len);
494   sig = silc_calloc(1, sizeof(*sig));
495   if (!sig)
496     return NULL;
497
498   /* Parse the payload */
499   ret = silc_buffer_unformat(&buffer,
500                              SILC_STR_UI_SHORT(&sig->pk_len),
501                              SILC_STR_UI_SHORT(&sig->pk_type),
502                              SILC_STR_END);
503   if (ret == -1 || sig->pk_len > data_len - 4) {
504     silc_message_signed_payload_free(sig);
505     SILC_LOG_DEBUG(("Malformed public key in SILC_MESSAGE_FLAG_SIGNED "
506                     "Payload"));
507     return NULL;
508   }
509
510   silc_buffer_pull(&buffer, 4);
511   ret = silc_buffer_unformat(&buffer,
512                              SILC_STR_UI_XNSTRING_ALLOC(&sig->pk_data,
513                                                         sig->pk_len),
514                              SILC_STR_UI16_NSTRING_ALLOC(&sig->sign_data,
515                                                          &sig->sign_len),
516                              SILC_STR_END);
517   if (ret == -1) {
518     silc_message_signed_payload_free(sig);
519     SILC_LOG_DEBUG(("Malformed SILC_MESSAGE_FLAG_SIGNED Payload"));
520     return NULL;
521   }
522   silc_buffer_push(&buffer, 4);
523
524   /* Signature must be provided */
525   if (sig->sign_len < 1)  {
526     SILC_LOG_DEBUG(("Malformed signature in SILC_MESSAGE_SIGNED_PAYLOAD "
527                     "Payload"));
528     silc_message_signed_payload_free(sig);
529     return NULL;
530   }
531
532   return sig;
533 }
534
535 /* Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the digital
536    signature. */
537
538 SilcBuffer
539 silc_message_signed_payload_encode(const unsigned char *message_payload,
540                                    SilcUInt32 message_payload_len,
541                                    SilcPublicKey public_key,
542                                    SilcPrivateKey private_key,
543                                    SilcHash hash)
544 {
545   SilcBuffer buffer, sign;
546   SilcPKCS pkcs;
547   unsigned char auth_data[2048 + 1];
548   SilcUInt32 auth_len;
549   unsigned char *pk = NULL;
550   SilcUInt32 pk_len = 0;
551   SilcUInt16 pk_type;
552
553   if (!message_payload || !message_payload_len || !private_key || !hash)
554     return NULL;
555   
556   if (public_key)
557     pk = silc_pkcs_public_key_encode(public_key, &pk_len);
558
559   /* Now we support only SILC style public key */
560   pk_type = SILC_SKE_PK_TYPE_SILC;
561
562   /* Encode the data to be signed */
563   sign = silc_message_signed_encode_data(message_payload,
564                                          message_payload_len,
565                                          pk, pk_len, pk_type);
566   if (!sign) {
567     silc_free(pk);
568     return NULL;
569   }
570
571   /* Sign the buffer */
572
573   /* Allocate PKCS object */
574   if (!silc_pkcs_alloc(private_key->name, &pkcs)) {
575     SILC_LOG_ERROR(("Could not allocated PKCS"));
576     silc_buffer_clear(sign);
577     silc_buffer_free(sign);
578     silc_free(pk);
579     return NULL;
580   }
581   silc_pkcs_private_key_set(pkcs, private_key);
582
583   /* Compute the hash and the signature. */
584   if (silc_pkcs_get_key_len(pkcs) / 8 > sizeof(auth_data) - 1 ||
585       !silc_pkcs_sign_with_hash(pkcs, hash, sign->data, sign->len, auth_data,
586                                 &auth_len)) {
587     SILC_LOG_ERROR(("Could not compute signature"));
588     silc_buffer_clear(sign);
589     silc_buffer_free(sign);
590     silc_pkcs_free(pkcs);
591     silc_free(pk);
592     return NULL;
593   }
594
595   /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */
596
597   buffer = silc_buffer_alloc_size(4 + pk_len + 2 + auth_len);
598   if (!buffer) {
599     silc_buffer_clear(sign);
600     silc_buffer_free(sign);
601     silc_pkcs_free(pkcs);
602     memset(auth_data, 0, sizeof(auth_data));
603     silc_free(pk);
604     return NULL;
605   }
606
607   silc_buffer_format(buffer,
608                      SILC_STR_UI_SHORT(pk_len),
609                      SILC_STR_UI_SHORT(pk_type),
610                      SILC_STR_END);
611
612   if (pk_len && pk) {
613     silc_buffer_pull(buffer, 4);
614     silc_buffer_format(buffer,
615                        SILC_STR_UI_XNSTRING(pk, pk_len),
616                        SILC_STR_END);
617     silc_buffer_push(buffer, 4);
618   }
619
620   silc_buffer_pull(buffer, 4 + pk_len);
621   silc_buffer_format(buffer,
622                      SILC_STR_UI_SHORT(auth_len),
623                      SILC_STR_UI_XNSTRING(auth_data, auth_len),
624                      SILC_STR_END);
625   silc_buffer_push(buffer, 4 + pk_len);
626
627   SILC_LOG_HEXDUMP(("sig payload"), buffer->data, buffer->len);
628
629   memset(auth_data, 0, sizeof(auth_data));
630   silc_pkcs_free(pkcs);
631   silc_buffer_clear(sign);
632   silc_buffer_free(sign);
633   silc_free(pk);
634
635   return buffer;
636 }
637
638 /* Free the payload */
639
640 void silc_message_signed_payload_free(SilcMessageSignedPayload sig)
641 {
642   memset(sig->sign_data, 0, sig->sign_len);
643   silc_free(sig->sign_data);
644   silc_free(sig->pk_data);
645   silc_free(sig);
646 }
647
648 /* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
649
650 int silc_message_signed_verify(SilcMessageSignedPayload sig,
651                                SilcMessagePayload message,
652                                SilcPublicKey remote_public_key,
653                                SilcHash hash)
654 {
655   int ret = SILC_AUTH_FAILED;
656   SilcBuffer sign;
657   SilcPKCS pkcs;
658   SilcBuffer tmp;
659   
660   if (!sig || !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, tmp->len,
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   /* Allocate PKCS object */
682   if (!silc_pkcs_alloc(remote_public_key->name, &pkcs)) {
683     silc_buffer_clear(sign);
684     silc_buffer_free(sign);
685     return ret;
686   }
687   silc_pkcs_public_key_set(pkcs, remote_public_key);
688
689   /* Verify the authentication data */
690   if (!silc_pkcs_verify_with_hash(pkcs, hash, sig->sign_data,
691                                   sig->sign_len,
692                                   sign->data, sign->len)) {
693
694     silc_buffer_clear(sign);
695     silc_buffer_free(sign);
696     silc_pkcs_free(pkcs);
697     SILC_LOG_DEBUG(("Signature verification failed"));
698     return ret;
699   }
700
701   ret = SILC_AUTH_OK;
702
703   silc_buffer_clear(sign);
704   silc_buffer_free(sign);
705   silc_pkcs_free(pkcs);
706
707   SILC_LOG_DEBUG(("Signature verification successful"));
708
709   return ret;
710 }
711
712 /* Return the public key from the payload */
713
714 SilcPublicKey
715 silc_message_signed_get_public_key(SilcMessageSignedPayload sig,
716                                    unsigned char **pk_data,
717                                    SilcUInt32 *pk_data_len)
718 {
719   SilcPublicKey pk;
720
721   if (!sig->pk_data || !silc_pkcs_public_key_decode(sig->pk_data,
722                                                     sig->pk_len, &pk))
723     return NULL;
724
725   if (pk_data)
726     *pk_data = sig->pk_data;
727   if (pk_data_len)
728     *pk_data_len = sig->pk_len;
729
730   return pk;
731 }