Protocol version 1.2 integrations
[silc.git] / lib / silccore / silcauth.c
1 /*
2
3   silcauth.c 
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2001 - 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 /* $Id$ */
20
21 #include "silcincludes.h"
22 #include "silcauth.h"
23 #include "silcchannel_i.h"
24 #include "silcprivate_i.h"
25
26 /******************************************************************************
27
28                            Authentication Payload
29
30 ******************************************************************************/
31
32 /* Authentication Payload structure */
33 struct SilcAuthPayloadStruct {
34   SilcUInt16 len;
35   SilcUInt16 auth_method;
36   SilcUInt16 random_len;
37   unsigned char *random_data;
38   SilcUInt16 auth_len;
39   unsigned char *auth_data;
40 };
41
42 /* Parses and returns Authentication Payload */
43
44 SilcAuthPayload silc_auth_payload_parse(const unsigned char *data,
45                                         SilcUInt32 data_len)
46 {
47   SilcBufferStruct buffer;
48   SilcAuthPayload newp;
49   int ret;
50
51   SILC_LOG_DEBUG(("Parsing Authentication Payload"));
52
53   silc_buffer_set(&buffer, (unsigned char *)data, data_len);
54   newp = silc_calloc(1, sizeof(*newp));
55   if (!newp)
56     return NULL;
57
58   /* Parse the payload */
59   ret = silc_buffer_unformat(&buffer,
60                              SILC_STR_UI_SHORT(&newp->len),
61                              SILC_STR_UI_SHORT(&newp->auth_method),
62                              SILC_STR_UI16_NSTRING_ALLOC(&newp->random_data,
63                                                          &newp->random_len),
64                              SILC_STR_UI16_NSTRING_ALLOC(&newp->auth_data,
65                                                          &newp->auth_len),
66                              SILC_STR_END);
67   if (ret == -1) {
68     silc_free(newp);
69     return NULL;
70   }
71
72   if (newp->len != buffer.len || 
73       newp->random_len + newp->auth_len > buffer.len - 8) {
74     silc_auth_payload_free(newp);
75     return NULL;
76   }
77
78   /* Authentication data must be provided */
79   if (newp->auth_len < 1)  {
80     silc_auth_payload_free(newp);
81     return NULL;
82   }
83
84   /* If password authentication, random data must not be set */
85   if (newp->auth_method == SILC_AUTH_PASSWORD && newp->random_len) {
86     silc_auth_payload_free(newp);
87     return NULL;
88   }
89
90   /* If public key authentication, random data must be at least 128 bytes */
91   if (newp->auth_method == SILC_AUTH_PUBLIC_KEY && newp->random_len < 128) {
92     silc_auth_payload_free(newp);
93     return NULL;
94   }
95
96   return newp;
97 }
98
99 /* Encodes authentication payload into buffer and returns it */
100
101 SilcBuffer silc_auth_payload_encode(SilcAuthMethod method,
102                                     const unsigned char *random_data,
103                                     SilcUInt16 random_len,
104                                     const unsigned char *auth_data,
105                                     SilcUInt16 auth_len)
106 {
107   SilcBuffer buffer;
108   SilcUInt32 len;
109   unsigned char *autf8 = NULL;
110   SilcUInt32 autf8_len;
111
112   SILC_LOG_DEBUG(("Encoding Authentication Payload"));
113
114   /* Passphrase MUST be UTF-8 encoded, encode if it is not */
115   if (method == SILC_AUTH_PASSWORD && !silc_utf8_valid(auth_data, auth_len)) {
116     autf8_len = silc_utf8_encoded_len(auth_data, auth_len, 0);
117     if (!autf8_len)
118       return NULL;
119     autf8 = silc_calloc(autf8_len, sizeof(*autf8));
120     auth_len = silc_utf8_encode(auth_data, auth_len, 0, autf8, autf8_len);
121     auth_data = (const unsigned char *)autf8;
122   }
123
124   len = 2 + 2 + 2 + random_len + 2 + auth_len;
125   buffer = silc_buffer_alloc_size(len);
126   if (!buffer) {
127     silc_free(autf8);
128     return NULL;
129   }
130
131   silc_buffer_format(buffer,
132                      SILC_STR_UI_SHORT(len),
133                      SILC_STR_UI_SHORT(method),
134                      SILC_STR_UI_SHORT(random_len),
135                      SILC_STR_UI_XNSTRING(random_data, random_len),
136                      SILC_STR_UI_SHORT(auth_len),
137                      SILC_STR_UI_XNSTRING(auth_data, auth_len),
138                      SILC_STR_END);
139
140   silc_free(autf8);
141   return buffer;
142 }
143
144 /* Frees authentication payload. */
145
146 void silc_auth_payload_free(SilcAuthPayload payload)
147 {
148   if (payload) {
149     if (payload->random_data) {
150       memset(payload->random_data, 0, payload->random_len);
151       silc_free(payload->random_data);
152     }
153     if (payload->auth_data) {
154       memset(payload->auth_data, 0, payload->auth_len);
155       silc_free(payload->auth_data);
156     }
157     silc_free(payload);
158   }
159 }
160
161 /* Get authentication method */
162
163 SilcAuthMethod silc_auth_get_method(SilcAuthPayload payload)
164 {
165   return payload->auth_method;
166 }
167
168 /* Get the authentication data. If this is passphrase it is UTF-8 encoded. */
169
170 unsigned char *silc_auth_get_data(SilcAuthPayload payload,
171                                   SilcUInt32 *auth_len)
172 {
173   if (auth_len)
174     *auth_len = payload->auth_len;
175
176   return payload->auth_data;
177 }
178
179 /******************************************************************************
180
181                            Authentication Routines
182
183 ******************************************************************************/
184
185 /* Encodes the authentication data for hashing and signing as the protocol
186    dictates. */
187
188 static unsigned char *
189 silc_auth_public_key_encode_data(SilcPublicKey public_key,
190                                  const unsigned char *randomdata,
191                                  SilcUInt32 random_len, const void *id,
192                                  SilcIdType type, SilcUInt32 *ret_len)
193 {
194   SilcBuffer buf;
195   unsigned char *pk, *id_data, *ret;
196   SilcUInt32 pk_len, id_len;
197
198   pk = silc_pkcs_public_key_encode(public_key, &pk_len);
199   if (!pk)
200     return NULL;
201
202   id_data = silc_id_id2str(id, type);
203   if (!id_data) {
204     silc_free(pk);
205     return NULL;
206   }
207   id_len = silc_id_get_len(id, type);
208
209   buf = silc_buffer_alloc_size(random_len + id_len + pk_len);
210   if (!buf) {
211     silc_free(pk);
212     silc_free(id_data);
213     return NULL;
214   }
215   silc_buffer_format(buf,
216                      SILC_STR_UI_XNSTRING(randomdata, random_len),
217                      SILC_STR_UI_XNSTRING(id_data, id_len),
218                      SILC_STR_UI_XNSTRING(pk, pk_len),
219                      SILC_STR_END);
220
221   ret = silc_memdup(buf->data, buf->len);
222   if (!ret)
223     return NULL;
224
225   if (ret_len)
226     *ret_len = buf->len;
227
228   silc_buffer_clear(buf);
229   silc_buffer_free(buf);
230   silc_free(id_data);
231   silc_free(pk);
232
233   return ret;
234 }
235
236 /* Generates Authentication Payload with authentication data. This is used
237    to do public key based authentication. This generates the random data
238    and the actual authentication data. Returns NULL on error. */
239
240 SilcBuffer silc_auth_public_key_auth_generate(SilcPublicKey public_key,
241                                               SilcPrivateKey private_key,
242                                               SilcRng rng, SilcHash hash,
243                                               const void *id, SilcIdType type)
244 {
245   unsigned char *randomdata;
246   unsigned char auth_data[2048];
247   SilcUInt32 auth_len;
248   unsigned char *tmp;
249   SilcUInt32 tmp_len;
250   SilcBuffer buf;
251   SilcPKCS pkcs;
252
253   SILC_LOG_DEBUG(("Generating Authentication Payload with data"));
254
255   /* Get 256 bytes of random data */
256   if (rng)
257     randomdata = silc_rng_get_rn_data(rng, 256);
258   else
259     randomdata = silc_rng_global_get_rn_data(256);
260   if (!randomdata)
261     return NULL;
262
263   /* Encode the auth data */
264   tmp = silc_auth_public_key_encode_data(public_key, randomdata, 256, id, 
265                                          type, &tmp_len);
266   if (!tmp)
267     return NULL;
268
269   /* Allocate PKCS object */
270   if (!silc_pkcs_alloc(private_key->name, &pkcs)) {
271     memset(tmp, 0, tmp_len);
272     silc_free(tmp);
273     return NULL;
274   }
275   silc_pkcs_public_key_set(pkcs, public_key);
276   silc_pkcs_private_key_set(pkcs, private_key);
277
278   /* Compute the hash and the signature. */
279   if (silc_pkcs_get_key_len(pkcs) / 8 > sizeof(auth_data) - 1 ||
280       !silc_pkcs_sign_with_hash(pkcs, hash, tmp, tmp_len, auth_data,
281                                 &auth_len)) {
282     memset(randomdata, 0, 256);
283     memset(tmp, 0, tmp_len);
284     silc_free(tmp);
285     silc_free(randomdata);
286     silc_pkcs_free(pkcs);
287     return NULL;
288   }
289
290   /* Encode Authentication Payload */
291   buf = silc_auth_payload_encode(SILC_AUTH_PUBLIC_KEY, randomdata, 256,
292                                  auth_data, auth_len);
293
294   memset(tmp, 0, tmp_len);
295   memset(auth_data, 0, sizeof(auth_data));
296   memset(randomdata, 0, 256);
297   silc_free(tmp);
298   silc_free(randomdata);
299   silc_pkcs_free(pkcs);
300
301   return buf;
302 }
303
304 /* Verifies the authentication data. Returns TRUE if authentication was
305    successful. */
306
307 bool silc_auth_public_key_auth_verify(SilcAuthPayload payload,
308                                       SilcPublicKey public_key, SilcHash hash,
309                                       const void *id, SilcIdType type)
310 {
311   unsigned char *tmp;
312   SilcUInt32 tmp_len;
313   SilcPKCS pkcs;
314
315   SILC_LOG_DEBUG(("Verifying authentication data"));
316
317   /* Encode auth data */
318   tmp = silc_auth_public_key_encode_data(public_key, payload->random_data,
319                                          payload->random_len,
320                                          id, type, &tmp_len);
321   if (!tmp) {
322     SILC_LOG_DEBUG(("Authentication failed"));
323     return FALSE;
324   }
325
326   /* Allocate PKCS object */
327   if (!silc_pkcs_alloc(public_key->name, &pkcs)) {
328     memset(tmp, 0, tmp_len);
329     silc_free(tmp);
330     return FALSE;
331   }
332   silc_pkcs_public_key_set(pkcs, public_key);
333
334   /* Verify the authentication data */
335   if (!silc_pkcs_verify_with_hash(pkcs, hash, payload->auth_data,
336                                   payload->auth_len, tmp, tmp_len)) {
337
338     memset(tmp, 0, tmp_len);
339     silc_free(tmp);
340     silc_pkcs_free(pkcs);
341     SILC_LOG_DEBUG(("Authentication failed"));
342     return FALSE;
343   }
344
345   memset(tmp, 0, tmp_len);
346   silc_free(tmp);
347   silc_pkcs_free(pkcs);
348
349   SILC_LOG_DEBUG(("Authentication successful"));
350
351   return TRUE;
352 }
353
354 /* Same as above but the payload is not parsed yet. This will parse it. */
355
356 bool silc_auth_public_key_auth_verify_data(const unsigned char *payload,
357                                            SilcUInt32 payload_len,
358                                            SilcPublicKey public_key,
359                                            SilcHash hash,
360                                            const void *id, SilcIdType type)
361 {
362   SilcAuthPayload auth_payload;
363   int ret;
364
365   auth_payload = silc_auth_payload_parse(payload, payload_len);
366   if (!auth_payload) {
367     SILC_LOG_DEBUG(("Authentication failed"));
368     return FALSE;
369   }
370
371   ret = silc_auth_public_key_auth_verify(auth_payload, public_key, hash,
372                                          id, type);
373
374   silc_auth_payload_free(auth_payload);
375
376   return ret;
377 }
378
379 /* Verifies the authentication data directly from the Authentication
380    Payload. Supports all authentication methods. If the authentication
381    method is passphrase based then the `auth_data' and `auth_data_len'
382    are the passphrase and its length. If the method is public key
383    authentication then the `auth_data' is the SilcPublicKey and the
384    `auth_data_len' is ignored. */
385
386 bool silc_auth_verify(SilcAuthPayload payload, SilcAuthMethod auth_method,
387                       const void *auth_data, SilcUInt32 auth_data_len,
388                       SilcHash hash, const void *id, SilcIdType type)
389 {
390   SILC_LOG_DEBUG(("Verifying authentication"));
391
392   if (!payload || auth_method != payload->auth_method)
393     return FALSE;
394
395   switch (payload->auth_method) {
396   case SILC_AUTH_NONE:
397     /* No authentication */
398     SILC_LOG_DEBUG(("No authentication required"));
399     return TRUE;
400
401   case SILC_AUTH_PASSWORD:
402     /* Passphrase based authentication. The `pkcs', `hash', `id' and `type'
403        arguments are not needed. */
404
405     /* Sanity checks */
406     if ((payload->auth_len == 0) || !auth_data ||
407         payload->auth_len != auth_data_len)
408       break;
409
410     if (!memcmp(payload->auth_data, auth_data, auth_data_len)) {
411       SILC_LOG_DEBUG(("Passphrase Authentication successful"));
412       return TRUE;
413     }
414     break;
415
416   case SILC_AUTH_PUBLIC_KEY:
417     /* Public key based authentication */
418     return silc_auth_public_key_auth_verify(payload, (SilcPublicKey)auth_data,
419                                             hash, id, type);
420     break;
421
422   default:
423     break;
424   }
425
426   SILC_LOG_DEBUG(("Authentication failed"));
427
428   return FALSE;
429 }
430
431 /* Same as above but parses the authentication payload before verify. */
432
433 bool silc_auth_verify_data(const unsigned char *payload,
434                            SilcUInt32 payload_len,
435                            SilcAuthMethod auth_method, const void *auth_data,
436                            SilcUInt32 auth_data_len, SilcHash hash,
437                            const void *id, SilcIdType type)
438 {
439   SilcAuthPayload auth_payload;
440   bool ret;
441
442   auth_payload = silc_auth_payload_parse(payload, payload_len);
443   if (!auth_payload || (auth_payload->auth_len == 0))
444     return FALSE;
445
446   ret = silc_auth_verify(auth_payload, auth_method, auth_data, auth_data_len,
447                          hash, id, type);
448
449   silc_auth_payload_free(auth_payload);
450
451   return ret;
452 }
453
454 /******************************************************************************
455
456                             Key Agreement Payload
457
458 ******************************************************************************/
459
460 /* The Key Agreement protocol structure */
461 struct SilcKeyAgreementPayloadStruct {
462   SilcUInt16 hostname_len;
463   unsigned char *hostname;
464   SilcUInt32 port;
465 };
466
467 /* Parses and returns an allocated Key Agreement payload. */
468
469 SilcKeyAgreementPayload
470 silc_key_agreement_payload_parse(const unsigned char *payload,
471                                  SilcUInt32 payload_len)
472 {
473   SilcBufferStruct buffer;
474   SilcKeyAgreementPayload newp;
475   int ret;
476
477   SILC_LOG_DEBUG(("Parsing Key Agreement Payload"));
478
479   silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
480   newp = silc_calloc(1, sizeof(*newp));
481   if (!newp)
482     return NULL;
483
484   /* Parse the payload */
485   ret = silc_buffer_unformat(&buffer,
486                              SILC_STR_UI16_NSTRING_ALLOC(&newp->hostname,
487                                                          &newp->hostname_len),
488                              SILC_STR_UI_INT(&newp->port),
489                              SILC_STR_END);
490   if (ret == -1) {
491     silc_free(newp);
492     return NULL;
493   }
494
495   return newp;
496 }
497
498 /* Encodes the Key Agreement protocol and returns the encoded buffer */
499
500 SilcBuffer silc_key_agreement_payload_encode(const char *hostname,
501                                              SilcUInt32 port)
502 {
503   SilcBuffer buffer;
504   SilcUInt32 len = hostname ? strlen(hostname) : 0;
505
506   SILC_LOG_DEBUG(("Encoding Key Agreement Payload"));
507
508   buffer = silc_buffer_alloc_size(2 + len + 4);
509   if (!buffer)
510     return NULL;
511   silc_buffer_format(buffer,
512                      SILC_STR_UI_SHORT(len),
513                      SILC_STR_UI_XNSTRING(hostname, len),
514                      SILC_STR_UI_INT(port),
515                      SILC_STR_END);
516
517   return buffer;
518 }
519
520 /* Frees the Key Agreement protocol */
521
522 void silc_key_agreement_payload_free(SilcKeyAgreementPayload payload)
523 {
524   if (payload) {
525     silc_free(payload->hostname);
526     silc_free(payload);
527   }
528 }
529
530 /* Returns the hostname in the payload */
531
532 char *silc_key_agreement_get_hostname(SilcKeyAgreementPayload payload)
533 {
534   return payload->hostname;
535 }
536
537 /* Returns the port in the payload */
538
539 SilcUInt32 silc_key_agreement_get_port(SilcKeyAgreementPayload payload)
540 {
541   return payload->port;
542 }
543
544 /******************************************************************************
545
546                      SILC_MESSAGE_FLAG_SIGNED Payload
547
548 ******************************************************************************/
549
550 /* The SILC_MESSAGE_FLAG_SIGNED Payload */
551 struct SilcSignedPayloadStruct {
552   SilcUInt16 pk_len;
553   SilcUInt16 pk_type;
554   SilcUInt16 sign_len;
555   unsigned char *pk_data;
556   unsigned char *sign_data;
557 };
558
559 /* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */
560
561 static SilcBuffer
562 silc_signed_payload_encode_data(const unsigned char *message_payload,
563                                 SilcUInt32 message_payload_len,
564                                 unsigned char *pk,
565                                 SilcUInt32 pk_len, SilcUInt32 pk_type)
566 {
567   SilcBuffer sign;
568
569   sign = silc_buffer_alloc_size(message_payload_len + 4 + pk_len);
570   if (!sign)
571     return NULL;
572
573   silc_buffer_format(sign,
574                      SILC_STR_UI_XNSTRING(message_payload,
575                                           message_payload_len),
576                      SILC_STR_UI_SHORT(pk_len),
577                      SILC_STR_UI_SHORT(pk_type),
578                      SILC_STR_END);
579
580   if (pk && pk_len) {
581     silc_buffer_pull(sign, message_payload_len + 4);
582     silc_buffer_format(sign,
583                        SILC_STR_UI_XNSTRING(pk, pk_len),
584                        SILC_STR_END);
585     silc_buffer_push(sign, message_payload_len + 4);
586   }
587
588   return sign;
589 }
590
591 /* Parses the SILC_MESSAGE_FLAG_SIGNED Payload */
592
593 SilcSignedPayload silc_signed_payload_parse(const unsigned char *data,
594                                             SilcUInt32 data_len)
595 {
596   SilcSignedPayload sig;
597   SilcBufferStruct buffer;
598   int ret;
599
600   SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload"));
601
602   silc_buffer_set(&buffer, (unsigned char *)data, data_len);
603   sig = silc_calloc(1, sizeof(*sig));
604   if (!sig)
605     return NULL;
606
607   /* Parse the payload */
608   ret = silc_buffer_unformat(&buffer,
609                              SILC_STR_UI_SHORT(&sig->pk_len),
610                              SILC_STR_UI_SHORT(&sig->pk_type),
611                              SILC_STR_END);
612   if (ret == -1 || sig->pk_len > data_len - 4) {
613     silc_signed_payload_free(sig);
614     return NULL;
615   }
616
617   silc_buffer_pull(&buffer, 4);
618   ret = silc_buffer_unformat(&buffer,
619                              SILC_STR_UI_XNSTRING_ALLOC(&sig->pk_data,
620                                                         sig->pk_len),
621                              SILC_STR_UI16_NSTRING_ALLOC(&sig->sign_data,
622                                                          &sig->sign_len),
623                              SILC_STR_END);
624   if (ret == -1) {
625     silc_signed_payload_free(sig);
626     return NULL;
627   }
628   silc_buffer_push(&buffer, 4);
629
630   /* Signature must be provided */
631   if (sig->sign_len < 1)  {
632     silc_signed_payload_free(sig);
633     return NULL;
634   }
635
636   return sig;
637 }
638
639 /* Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the digital
640    signature. */
641
642 SilcBuffer silc_signed_payload_encode(const unsigned char *message_payload,
643                                       SilcUInt32 message_payload_len,
644                                       SilcPublicKey public_key,
645                                       SilcPrivateKey private_key,
646                                       SilcHash hash,
647                                       bool include_public_key)
648 {
649   SilcBuffer buffer, sign;
650   SilcPKCS pkcs;
651   unsigned char auth_data[2048];
652   SilcUInt32 auth_len;
653   unsigned char *pk = NULL;
654   SilcUInt32 pk_len = 0;
655   SilcUInt16 pk_type;
656
657   if (!message_payload || !message_payload_len || !private_key || !hash)
658     return NULL;
659   if (include_public_key && !public_key)
660     return NULL;
661
662   if (include_public_key)
663     pk = silc_pkcs_public_key_encode(public_key, &pk_len);
664
665   /* Now we support only SILC style public key */
666   pk_type = SILC_SKE_PK_TYPE_SILC;
667
668   /* Encode the data to be signed */
669   sign = silc_signed_payload_encode_data(message_payload,
670                                          message_payload_len,
671                                          pk, pk_len, pk_type);
672   if (!sign) {
673     silc_free(pk);
674     return NULL;
675   }
676
677   /* Sign the buffer */
678
679   /* Allocate PKCS object */
680   if (!silc_pkcs_alloc(private_key->name, &pkcs)) {
681     silc_buffer_clear(sign);
682     silc_buffer_free(sign);
683     silc_free(pk);
684     return NULL;
685   }
686   silc_pkcs_private_key_set(pkcs, private_key);
687
688   /* Compute the hash and the signature. */
689   if (silc_pkcs_get_key_len(pkcs) / 8 > sizeof(auth_data) - 1 ||
690       !silc_pkcs_sign_with_hash(pkcs, hash, sign->data, sign->len, auth_data,
691                                 &auth_len)) {
692     silc_buffer_clear(sign);
693     silc_buffer_free(sign);
694     silc_pkcs_free(pkcs);
695     silc_free(pk);
696     return NULL;
697   }
698
699   /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */
700
701   buffer = silc_buffer_alloc_size(4 + pk_len + 2 + auth_len);
702   if (!buffer) {
703     silc_buffer_clear(sign);
704     silc_buffer_free(sign);
705     silc_pkcs_free(pkcs);
706     memset(auth_data, 0, sizeof(auth_data));
707     silc_free(pk);
708     return NULL;
709   }
710
711   silc_buffer_format(sign,
712                      SILC_STR_UI_SHORT(pk_len),
713                      SILC_STR_UI_SHORT(pk_type),
714                      SILC_STR_END);
715
716   if (pk_len && pk) {
717     silc_buffer_pull(sign, 4);
718     silc_buffer_format(sign,
719                        SILC_STR_UI_XNSTRING(pk, pk_len),
720                        SILC_STR_END);
721     silc_buffer_push(sign, 4);
722   }
723
724   silc_buffer_pull(sign, 4 + pk_len);
725   silc_buffer_format(sign,
726                      SILC_STR_UI_SHORT(auth_len),
727                      SILC_STR_UI_XNSTRING(auth_data, auth_len),
728                      SILC_STR_END);
729   silc_buffer_push(sign, 4 + pk_len);
730
731   memset(auth_data, 0, sizeof(auth_data));
732   silc_pkcs_free(pkcs);
733   silc_buffer_clear(sign);
734   silc_buffer_free(sign);
735   silc_free(pk);
736
737   return buffer;
738 }
739
740 /* Free the payload */
741
742 void silc_signed_payload_free(SilcSignedPayload sig)
743 {
744   if (sig) {
745     memset(sig->sign_data, 0, sig->sign_len);
746     silc_free(sig->sign_data);
747     silc_free(sig->pk_data);
748     silc_free(sig);
749   }
750 }
751
752 /* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
753
754 int silc_signed_payload_verify(SilcSignedPayload sig,
755                                bool channel_message,
756                                void *message_payload,
757                                SilcPublicKey remote_public_key,
758                                SilcHash hash)
759 {
760   int ret = SILC_AUTH_FAILED;
761 #if 0
762   SilcBuffer sign;
763   SilcPKCS pkcs;
764   
765   if (!sig || !remote_public_key || !hash)
766     return ret;
767
768   /* Generate the signature verification data */
769   if (channel_message) {
770     SilcChannelMessagePayload chm =
771       (SilcChannelMessagePayload)message_payload;
772     SilcBuffer tmp;
773
774     /* Encode Channel Message Payload */
775     tmp = silc_buffer_alloc_size(6 + chm->data_len + chm->pad_len +
776                                  chm->iv_len);
777     silc_buffer_format(tmp,
778                        SILC_STR_UI_SHORT(chm->flags),
779                        SILC_STR_UI_SHORT(chm->data_len),
780                        SILC_STR_UI_XNSTRING(chm->data, chm->data_len),
781                        SILC_STR_UI_SHORT(chm->pad_len),
782                        SILC_STR_UI_XNSTRING(chm->pad, chm->pad_len),
783                        SILC_STR_UI_XNSTRING(chm->iv, chm->iv_len),
784                        SILC_STR_END);
785
786     sign = silc_signed_payload_encode_data(tmp->data, tmp->len,
787                                            sig->pk_data, sig->pk_len,
788                                            sig->pk_type);
789     silc_buffer_clear(tmp);
790     silc_buffer_free(tmp);
791   } else {
792     SilcPrivateMessagePayload prm =
793       (SilcPrivateMessagePayload)message_payload;
794     SilcBuffer tmp;
795
796     /* Encode Private Message Payload */
797     tmp = silc_buffer_alloc_size(4 + prm->data_len +
798                                  SILC_PRIVATE_MESSAGE_PAD(4 + prm->data_len));
799     silc_buffer_format(tmp,
800                        SILC_STR_UI_SHORT(prm->flags),
801                        SILC_STR_UI_SHORT(prm->message_len),
802                        SILC_STR_UI_XNSTRING(prm->message, prm->message_len),
803                        SILC_STR_END);
804
805     sign = silc_signed_payload_encode_data(tmp->data, tmp->len,
806                                            sig->pk_data, sig->pk_len,
807                                            sig->pk_type);
808     silc_buffer_clear(tmp);
809     silc_buffer_free(tmp);
810   }
811
812   if (!sign)
813     return ret;
814   
815   /* Allocate PKCS object */
816   if (!silc_pkcs_alloc(remote_public_key->name, &pkcs)) {
817     silc_buffer_clear(sign);
818     silc_buffer_free(sign);
819     return ret;
820   }
821   silc_pkcs_public_key_set(pkcs, remote_public_key);
822
823   /* Verify the authentication data */
824   if (!silc_pkcs_verify_with_hash(pkcs, hash, payload->sign_data
825                                   payload->sign_len,
826                                   sign->data, sign->len)) {
827
828     silc_buffer_clear(sign);
829     silc_buffer_free(sign);
830     silc_pkcs_free(pkcs);
831     SILC_LOG_DEBUG(("Signature verification failed"));
832     return ret;
833   }
834
835   ret = SILC_AUTH_OK;
836
837   silc_buffer_clear(sign);
838   silc_buffer_free(sign);
839   silc_pkcs_free(pkcs);
840
841   SILC_LOG_DEBUG(("Signature verification successful"));
842
843 #endif
844   return ret;
845 }
846
847 /* Return the public key from the payload */
848
849 SilcPublicKey silc_signed_payload_get_public_key(SilcSignedPayload sig)
850 {
851   SilcPublicKey pk;
852
853   if (!sig->pk_data || !silc_pkcs_public_key_decode(sig->pk_data,
854                                                     sig->pk_len, &pk))
855     return NULL;
856
857   return pk;
858 }