Sign payload buffer fixes.
[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 /******************************************************************************
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 SilcBool silc_message_payload_decrypt(unsigned char *data,
63                                   size_t data_len,
64                                   SilcBool private_message,
65                                   SilcBool static_key,
66                                   SilcCipher cipher,
67                                   SilcHmac hmac,
68                                   SilcBool 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 + iv_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                            SilcBool private_message,
152                            SilcBool 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, silc_buffer_len(&buffer),
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 > silc_buffer_len(&buffer) - 6 - mac_len - iv_len) ||
198       (newp->pad_len + newp->data_len > silc_buffer_len(&buffer) - 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 < silc_buffer_len(&buffer)) {
206     newp->sig =
207       silc_message_signed_payload_parse(buffer.data + 6 + newp->data_len +
208                                         newp->pad_len,
209                                         silc_buffer_len(&buffer) - iv_len - mac_len);
210   }
211
212   /* Parse IV and MAC from the payload */
213   if (iv_len) {
214     newp->iv = buffer.data + (silc_buffer_len(&buffer) - iv_len - mac_len);
215     newp->iv_len = iv_len;
216   }
217   if (mac_len)
218     newp->mac = buffer.data + (silc_buffer_len(&buffer) - 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 SilcBool 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                                        SilcBool generate_iv,
267                                        SilcBool 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,
339                                              silc_buffer_len(buffer),
340                                              public_key, private_key, hash);
341     if (sig) {
342       buffer = silc_buffer_realloc(buffer, silc_buffer_truelen(buffer) +
343                                    silc_buffer_len(sig));
344       if (buffer) {
345         silc_buffer_pull(buffer, 6 + data_len + pad_len);
346         silc_buffer_pull_tail(buffer, silc_buffer_len(sig));
347         silc_buffer_put(buffer, sig->data, silc_buffer_len(sig));
348         silc_buffer_push(buffer, 6 + data_len + pad_len);
349       }
350     }
351   }
352
353   /* Put IV */
354   silc_buffer_pull(buffer, 6 + data_len + pad_len +
355                    (sig ? silc_buffer_len(sig) : 0));
356   silc_buffer_pull_tail(buffer, iv_len);
357   silc_buffer_format(buffer,
358                      SILC_STR_UI_XNSTRING(iv, iv_len),
359                      SILC_STR_END);
360   silc_buffer_push(buffer, 6 + data_len + pad_len +
361                    (sig ? silc_buffer_len(sig) : 0));
362
363   /* Now encrypt the Message Payload and compute MAC */
364   if (cipher) {
365     if (!silc_message_payload_encrypt(buffer->data,
366                                       silc_buffer_len(buffer) - iv_len -
367                                       (sig ? silc_buffer_len(sig) : 0),
368                                       silc_buffer_len(buffer), iv, iv_len,
369                                       cipher, hmac)) {
370       silc_buffer_free(buffer);
371       silc_buffer_free(sig);
372       return NULL;
373     }
374   }
375   silc_buffer_pull_tail(buffer, silc_buffer_truelen(buffer) -
376                         silc_buffer_len(buffer));
377
378   silc_buffer_free(sig);
379   return buffer;
380 }
381
382 /* Free's Message Payload */
383
384 void silc_message_payload_free(SilcMessagePayload payload)
385 {
386   if (payload->data) {
387     memset(payload->data, 0, payload->data_len);
388     silc_free(payload->data);
389   }
390   if (payload->sig)
391     silc_message_signed_payload_free(payload->sig);
392   silc_free(payload->pad);
393   silc_free(payload);
394 }
395
396 /* Return flags */
397
398 SilcMessageFlags silc_message_get_flags(SilcMessagePayload payload)
399 {
400   return payload->flags;
401 }
402
403 /* Return data */
404
405 unsigned char *silc_message_get_data(SilcMessagePayload payload,
406                                      SilcUInt32 *data_len)
407 {
408   if (data_len)
409     *data_len = payload->data_len;
410   return payload->data;
411 }
412
413 /* Return MAC. The caller knows the length of the MAC */
414
415 unsigned char *silc_message_get_mac(SilcMessagePayload payload)
416 {
417   return payload->mac;
418 }
419
420 /* Return IV. The caller knows the length of the IV */
421
422 unsigned char *silc_message_get_iv(SilcMessagePayload payload)
423 {
424   return payload->iv;
425 }
426
427 /* Return signature of the message */
428
429 SilcMessageSignedPayload
430 silc_message_get_signature(SilcMessagePayload payload)
431 {
432   return payload->sig;
433 }
434
435 /******************************************************************************
436
437                      SILC_MESSAGE_FLAG_SIGNED Payload
438
439 ******************************************************************************/
440
441 /* The SILC_MESSAGE_FLAG_SIGNED Payload */
442 struct SilcMessageSignedPayloadStruct {
443   SilcUInt16 pk_len;
444   SilcUInt16 pk_type;
445   SilcUInt16 sign_len;
446   unsigned char *pk_data;
447   unsigned char *sign_data;
448 };
449
450 /* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */
451
452 static SilcBuffer
453 silc_message_signed_encode_data(const unsigned char *message_payload,
454                                 SilcUInt32 message_payload_len,
455                                 unsigned char *pk,
456                                 SilcUInt32 pk_len, SilcUInt32 pk_type)
457 {
458   SilcBuffer sign;
459
460   sign = silc_buffer_alloc_size(message_payload_len + 4 + pk_len);
461   if (!sign)
462     return NULL;
463
464   silc_buffer_format(sign,
465                      SILC_STR_UI_XNSTRING(message_payload,
466                                           message_payload_len),
467                      SILC_STR_UI_SHORT(pk_len),
468                      SILC_STR_UI_SHORT(pk_type),
469                      SILC_STR_END);
470
471   if (pk && pk_len) {
472     silc_buffer_pull(sign, message_payload_len + 4);
473     silc_buffer_format(sign,
474                        SILC_STR_UI_XNSTRING(pk, pk_len),
475                        SILC_STR_END);
476     silc_buffer_push(sign, message_payload_len + 4);
477   }
478
479   return sign;
480 }
481
482 /* Parses the SILC_MESSAGE_FLAG_SIGNED Payload */
483
484 SilcMessageSignedPayload
485 silc_message_signed_payload_parse(const unsigned char *data,
486                                   SilcUInt32 data_len)
487 {
488   SilcMessageSignedPayload sig;
489   SilcBufferStruct buffer;
490   int ret;
491
492   SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload"));
493
494   SILC_LOG_HEXDUMP(("sig payload"), (unsigned char *)data, data_len);
495
496   silc_buffer_set(&buffer, (unsigned char *)data, data_len);
497   sig = silc_calloc(1, sizeof(*sig));
498   if (!sig)
499     return NULL;
500
501   /* Parse the payload */
502   ret = silc_buffer_unformat(&buffer,
503                              SILC_STR_UI_SHORT(&sig->pk_len),
504                              SILC_STR_UI_SHORT(&sig->pk_type),
505                              SILC_STR_END);
506   if (ret == -1 || sig->pk_len > data_len - 4) {
507     silc_message_signed_payload_free(sig);
508     SILC_LOG_DEBUG(("Malformed public key in SILC_MESSAGE_FLAG_SIGNED "
509                     "Payload"));
510     return NULL;
511   }
512
513   silc_buffer_pull(&buffer, 4);
514   ret = silc_buffer_unformat(&buffer,
515                              SILC_STR_UI_XNSTRING_ALLOC(&sig->pk_data,
516                                                         sig->pk_len),
517                              SILC_STR_UI16_NSTRING_ALLOC(&sig->sign_data,
518                                                          &sig->sign_len),
519                              SILC_STR_END);
520   if (ret == -1 || sig->sign_len > silc_buffer_len(&buffer) - sig->pk_len - 2) {
521     silc_message_signed_payload_free(sig);
522     SILC_LOG_DEBUG(("Malformed SILC_MESSAGE_FLAG_SIGNED Payload"));
523     return NULL;
524   }
525   silc_buffer_push(&buffer, 4);
526
527   /* Signature must be provided */
528   if (sig->sign_len < 1)  {
529     SILC_LOG_DEBUG(("Malformed signature in SILC_MESSAGE_SIGNED_PAYLOAD "
530                     "Payload"));
531     silc_message_signed_payload_free(sig);
532     return NULL;
533   }
534
535   return sig;
536 }
537
538 /* Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the digital
539    signature. */
540
541 SilcBuffer
542 silc_message_signed_payload_encode(const unsigned char *message_payload,
543                                    SilcUInt32 message_payload_len,
544                                    SilcPublicKey public_key,
545                                    SilcPrivateKey private_key,
546                                    SilcHash hash)
547 {
548   SilcBuffer buffer, sign;
549   unsigned char auth_data[2048 + 1];
550   SilcUInt32 auth_len;
551   unsigned char *pk = NULL;
552   SilcUInt32 pk_len = 0;
553   SilcUInt16 pk_type;
554
555   if (!message_payload || !message_payload_len || !private_key || !hash)
556     return NULL;
557
558   if (public_key) {
559     pk = silc_pkcs_public_key_encode(public_key, &pk_len);
560     if (!pk)
561       return NULL;
562   }
563   pk_type = silc_pkcs_get_type(public_key);
564
565   /* Encode the data to be signed */
566   sign = silc_message_signed_encode_data(message_payload,
567                                          message_payload_len,
568                                          pk, pk_len, pk_type);
569   if (!sign) {
570     silc_free(pk);
571     return NULL;
572   }
573
574   /* Sign the buffer */
575
576   /* Compute the hash and the signature. */
577   if (!silc_pkcs_sign(private_key, sign->data, silc_buffer_len(sign),
578                       auth_data, sizeof(auth_data) - 1, &auth_len, hash)) {
579     SILC_LOG_ERROR(("Could not compute signature"));
580     silc_buffer_clear(sign);
581     silc_buffer_free(sign);
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     memset(auth_data, 0, sizeof(auth_data));
593     silc_free(pk);
594     return NULL;
595   }
596
597   silc_buffer_format(buffer,
598                      SILC_STR_UI_SHORT(pk_len),
599                      SILC_STR_UI_SHORT(pk_type),
600                      SILC_STR_END);
601
602   if (pk_len && pk) {
603     silc_buffer_pull(buffer, 4);
604     silc_buffer_format(buffer,
605                        SILC_STR_UI_XNSTRING(pk, pk_len),
606                        SILC_STR_END);
607     silc_buffer_push(buffer, 4);
608   }
609
610   silc_buffer_pull(buffer, 4 + pk_len);
611   silc_buffer_format(buffer,
612                      SILC_STR_UI_SHORT(auth_len),
613                      SILC_STR_UI_XNSTRING(auth_data, auth_len),
614                      SILC_STR_END);
615   silc_buffer_push(buffer, 4 + pk_len);
616
617   SILC_LOG_HEXDUMP(("sig payload"), buffer->data, silc_buffer_len(buffer));
618
619   memset(auth_data, 0, sizeof(auth_data));
620   silc_buffer_clear(sign);
621   silc_buffer_free(sign);
622   silc_free(pk);
623
624   return buffer;
625 }
626
627 /* Free the payload */
628
629 void silc_message_signed_payload_free(SilcMessageSignedPayload sig)
630 {
631   memset(sig->sign_data, 0, sig->sign_len);
632   silc_free(sig->sign_data);
633   silc_free(sig->pk_data);
634   silc_free(sig);
635 }
636
637 /* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
638
639 int silc_message_signed_verify(SilcMessageSignedPayload sig,
640                                SilcMessagePayload message,
641                                SilcPublicKey remote_public_key,
642                                SilcHash hash)
643 {
644   int ret = SILC_AUTH_FAILED;
645   SilcBuffer sign, tmp;
646
647   if (!sig || !remote_public_key || !hash)
648     return ret;
649
650   /* Generate the signature verification data, the Message Payload */
651   tmp = silc_buffer_alloc_size(6 + message->data_len + message->pad_len);
652   silc_buffer_format(tmp,
653                      SILC_STR_UI_SHORT(message->flags),
654                      SILC_STR_UI_SHORT(message->data_len),
655                      SILC_STR_UI_XNSTRING(message->data, message->data_len),
656                      SILC_STR_UI_SHORT(message->pad_len),
657                      SILC_STR_UI_XNSTRING(message->pad, message->pad_len),
658                      SILC_STR_END);
659   sign = silc_message_signed_encode_data(tmp->data, silc_buffer_len(tmp),
660                                          sig->pk_data, sig->pk_len,
661                                          sig->pk_type);
662   silc_buffer_clear(tmp);
663   silc_buffer_free(tmp);
664
665   if (!sign)
666     return ret;
667
668   /* Verify the authentication data */
669   if (!silc_pkcs_verify(remote_public_key, sig->sign_data,
670                         sig->sign_len,
671                         sign->data, silc_buffer_len(sign), hash)) {
672
673     silc_buffer_clear(sign);
674     silc_buffer_free(sign);
675     SILC_LOG_DEBUG(("Signature verification failed"));
676     return ret;
677   }
678
679   ret = SILC_AUTH_OK;
680
681   silc_buffer_clear(sign);
682   silc_buffer_free(sign);
683
684   SILC_LOG_DEBUG(("Signature verification successful"));
685
686   return ret;
687 }
688
689 /* Return the public key from the payload */
690
691 SilcPublicKey
692 silc_message_signed_get_public_key(SilcMessageSignedPayload sig,
693                                    const unsigned char **pk_data,
694                                    SilcUInt32 *pk_data_len)
695 {
696   SilcPublicKey pk;
697
698   if (!sig->pk_data)
699     return NULL;
700
701   if (!silc_pkcs_public_key_alloc(sig->pk_type, sig->pk_data,
702                                   sig->pk_len, &pk))
703     return NULL;
704
705   if (pk_data)
706     *pk_data = sig->pk_data;
707   if (pk_data_len)
708     *pk_data_len = sig->pk_len;
709
710   return pk;
711 }