Fixed parsing mesage payload.
[silc.git] / lib / silccore / silcmessage.c
1 /*
2
3   silcmessage.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2006 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /* Implementation of the Message Payload used as channel messages and
20    private messages. */
21 /* $Id$ */
22
23 #include "silc.h"
24 #include "silcmessage.h"
25
26 /*************************** Types and definitions **************************/
27
28 /* Calculates padding length for message payload */
29 #define SILC_MESSAGE_PAD(__payloadlen) (16 - ((__payloadlen) % 16))
30
31 /* Header length plus maximum padding length */
32 #define SILC_MESSAGE_HLEN 6 + 16
33
34 /* Returns the data length that fits to the packet.  If data length is too
35    big it will be truncated to fit to the payload. */
36 #define SILC_MESSAGE_DATALEN(data_len, header_len)              \
37   ((data_len + SILC_MESSAGE_HLEN + header_len) >                \
38    SILC_PACKET_MAX_LEN ?                                        \
39    data_len - ((data_len + SILC_MESSAGE_HLEN + header_len) -    \
40                SILC_PACKET_MAX_LEN) : data_len)
41
42 /* Message Payload structure. Contents of this structure is parsed
43    from SILC packets. */
44 struct SilcMessagePayloadStruct {
45   SilcMessageFlags flags;
46   SilcUInt16 data_len;
47   SilcUInt16 pad_len;
48   SilcUInt16 iv_len;
49   unsigned char *data;
50   unsigned char *pad;
51   unsigned char *mac;
52   SilcMessageSignedPayload sig;
53 };
54
55 /* Payload encoding context */
56 typedef struct {
57   SilcMessageFlags flags;
58   SilcPublicKey public_key;
59   SilcPrivateKey private_key;
60   SilcHash hash;
61   SilcCipher cipher;
62   SilcHmac hmac;
63   unsigned char *iv;
64   SilcUInt16 payload_len;
65 } SilcMessageEncode;
66
67
68 /****************************** Payload parsing *****************************/
69
70 /* Decrypts the Message Payload. The `data' is the actual Message Payload. */
71
72 SilcBool silc_message_payload_decrypt(unsigned char *data,
73                                       size_t data_len,
74                                       SilcBool private_message,
75                                       SilcBool static_key,
76                                       SilcCipher cipher,
77                                       SilcHmac hmac,
78                                       SilcBool check_mac)
79 {
80   SilcUInt32 mac_len, iv_len = 0, block_len;
81   SilcUInt16 len, totlen;
82   unsigned char mac[32], *ivp;
83
84   mac_len = silc_hmac_len(hmac);
85   block_len = silc_cipher_get_block_len(cipher);
86
87   /* IV is present for all channel messages, and private messages when
88      static key (pre-shared key) is used. */
89   if (!private_message || (private_message && static_key))
90     iv_len = block_len;
91
92   if (data_len <= (mac_len + iv_len))
93     return FALSE;
94
95   if (check_mac) {
96     /* Check the MAC of the message */
97     SILC_LOG_DEBUG(("Checking message MAC"));
98     silc_hmac_init(hmac);
99     silc_hmac_update(hmac, data, data_len - mac_len);
100     silc_hmac_final(hmac, mac, &mac_len);
101     if (memcmp(data + (data_len - mac_len), mac, mac_len)) {
102       SILC_LOG_DEBUG(("Message MAC does not match"));
103       return FALSE;
104     }
105     SILC_LOG_DEBUG(("MAC is Ok"));
106   }
107
108   /* Decrypt first only one block to get the header and then rest of
109      the data.  This is done because there might be unencrypted data at
110      the end and we don't know the encrypted length yet. */
111
112   /* Get pointer to the IV */
113   ivp = (iv_len ? data + (data_len - iv_len - mac_len) :
114          silc_cipher_get_iv(cipher));
115
116   /* Decrypt block */
117   if (!silc_cipher_decrypt(cipher, data, data, block_len, ivp))
118     return FALSE;
119
120   /* Get the payload length and decrypt rest */
121   totlen = 2;
122   SILC_GET16_MSB(len, data + totlen);
123   totlen += 2 + len;
124   if (totlen + iv_len + mac_len + 2 > data_len)
125     return FALSE;
126   if (totlen >= block_len)
127     if (!silc_cipher_decrypt(cipher, data + block_len, data + block_len,
128                              (totlen - block_len) + SILC_MESSAGE_PAD(totlen),
129                              ivp))
130       return FALSE;
131
132   return TRUE;
133 }
134
135 /* Parses Message Payload returning new payload structure.  This also
136    decrypts it and checks the MAC. */
137
138 SilcMessagePayload
139 silc_message_payload_parse(unsigned char *payload,
140                            SilcUInt32 payload_len,
141                            SilcBool private_message,
142                            SilcBool static_key,
143                            SilcCipher cipher,
144                            SilcHmac hmac)
145 {
146   SilcBufferStruct buffer;
147   SilcMessagePayload newp;
148   int ret;
149   SilcUInt32 mac_len = 0, iv_len = 0;
150
151   SILC_LOG_DEBUG(("Parsing Message Payload"));
152
153   silc_buffer_set(&buffer, payload, payload_len);
154
155   /* Decrypt the payload */
156   if (cipher) {
157     ret = silc_message_payload_decrypt(buffer.data, silc_buffer_len(&buffer),
158                                        private_message, static_key,
159                                        cipher, hmac, TRUE);
160     if (ret == FALSE)
161       return NULL;
162   }
163
164   if (hmac)
165     mac_len = silc_hmac_len(hmac);
166
167   /* IV is present for all channel messages, and private messages when
168      static key (pre-shared key) is used. */
169   if (cipher && (!private_message || (private_message && static_key)))
170     iv_len = silc_cipher_get_block_len(cipher);
171
172   newp = silc_calloc(1, sizeof(*newp));
173   if (!newp)
174     return NULL;
175
176   /* Parse the Message Payload. */
177   ret = silc_buffer_unformat(&buffer,
178                              SILC_STR_UI_SHORT(&newp->flags),
179                              SILC_STR_UI16_NSTRING_ALLOC(&newp->data,
180                                                          &newp->data_len),
181                              SILC_STR_UI16_NSTRING_ALLOC(&newp->pad,
182                                                          &newp->pad_len),
183                              SILC_STR_END);
184   if (ret == -1)
185     goto err;
186
187   if ((newp->data_len > silc_buffer_len(&buffer) - 6 - mac_len - iv_len) ||
188       (newp->pad_len + newp->data_len > silc_buffer_len(&buffer) -
189        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 +
197       iv_len < silc_buffer_len(&buffer)) {
198     newp->sig =
199       silc_message_signed_payload_parse(buffer.data + 6 + newp->data_len +
200                                         newp->pad_len,
201                                         silc_buffer_len(&buffer) -
202                                         iv_len - mac_len - 6 - newp->data_len -
203                                         newp->pad_len);
204   }
205
206   /* Parse MAC from the payload */
207   if (mac_len)
208     newp->mac = buffer.data + (silc_buffer_len(&buffer) - mac_len);
209
210   return newp;
211
212  err:
213   silc_message_payload_free(newp);
214   return NULL;
215 }
216
217
218 /***************************** Payload encoding *****************************/
219
220 /* This function is used to encrypt the Messsage Payload which is
221    the `data' and `data_len'.  This is used internally by the Message
222    Payload encoding routines but application may call this too if needed.
223    The `true_len' is the data length which is used to create MAC out of. */
224
225 SilcBool silc_message_payload_encrypt(unsigned char *data,
226                                       SilcUInt32 data_len,
227                                       SilcUInt32 true_len,
228                                       unsigned char *iv,
229                                       SilcCipher cipher,
230                                       SilcHmac hmac)
231 {
232   /* Encrypt payload of the packet */
233   if (!silc_cipher_encrypt(cipher, data, data, data_len, iv))
234     return FALSE;
235
236   /* Compute the MAC of the encrypted message data */
237   silc_hmac_init(hmac);
238   silc_hmac_update(hmac, data, true_len);
239   silc_hmac_final(hmac, data + true_len, NULL);
240
241   return TRUE;
242 }
243
244 /* Encrypt message payload */
245
246 static int silc_message_payload_encode_encrypt(SilcBuffer buffer,
247                                                void *value, void *context)
248 {
249   SilcMessageEncode *e = context;
250   SilcUInt32 mac_len;
251
252   if (!e->cipher || !e->hmac)
253     return 0;
254
255   mac_len = silc_hmac_len(e->hmac);
256   if (!silc_buffer_enlarge(buffer, mac_len))
257     return -1;
258
259   if (!silc_message_payload_encrypt(buffer->head,
260                                     e->payload_len,
261                                     silc_buffer_headlen(buffer),
262                                     e->iv, e->cipher, e->hmac))
263     return -1;
264
265   return mac_len;
266 }
267
268 /* Compute message signature */
269
270 static int silc_message_payload_encode_sig(SilcBuffer buffer,
271                                            void *value, void *context)
272 {
273   SilcMessageEncode *e = context;
274   SilcBuffer sig;
275   int len;
276
277   if (!(e->flags & SILC_MESSAGE_FLAG_SIGNED))
278     return 0;
279
280   sig = silc_message_signed_payload_encode(buffer->head,
281                                            silc_buffer_headlen(buffer),
282                                            e->public_key, e->private_key,
283                                            e->hash);
284   if (!sig)
285     return -1;
286
287   len = silc_buffer_format(buffer,
288                            SILC_STR_DATA(silc_buffer_data(sig),
289                                          silc_buffer_len(sig)),
290                            SILC_STR_END);
291   if (len < 0) {
292     silc_buffer_free(sig);
293     return -1;
294   }
295
296   silc_buffer_free(sig);
297   return len;
298 }
299
300 /* Encodes Message Payload into a buffer and returns it. */
301
302 SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
303                                        const unsigned char *data,
304                                        SilcUInt32 data_len,
305                                        SilcBool generate_iv,
306                                        SilcBool private_message,
307                                        SilcCipher cipher,
308                                        SilcHmac hmac,
309                                        SilcRng rng,
310                                        SilcPublicKey public_key,
311                                        SilcPrivateKey private_key,
312                                        SilcHash hash,
313                                        SilcBuffer buffer)
314 {
315   SilcUInt32 pad_len = 0, mac_len = 0, iv_len = 0;
316   unsigned char pad[16], iv[SILC_CIPHER_MAX_IV_SIZE];
317   SilcBuffer buf = NULL;
318   SilcMessageEncode e;
319   int i;
320
321   SILC_LOG_DEBUG(("Encoding Message Payload"));
322
323   if (!data_len)
324     return NULL;
325   if (!private_message && (!cipher || !hmac))
326     return NULL;
327
328   if (!buffer) {
329     buf = buffer = silc_buffer_alloc(0);
330     if (!buf)
331       return NULL;
332   }
333   silc_buffer_reset(buffer);
334
335   /* For channel messages IV is always generated */
336   if (!private_message && !generate_iv)
337     generate_iv = TRUE;
338
339   /* Generate IV */
340   if (cipher && generate_iv) {
341     iv_len = silc_cipher_get_block_len(cipher);
342     if (rng) {
343       for (i = 0; i < iv_len; i++) iv[i] = silc_rng_get_byte_fast(rng);
344     } else {
345       for (i = 0; i < iv_len; i++) iv[i] = silc_rng_global_get_byte_fast();
346     }
347   }
348
349   if (hmac)
350     mac_len = silc_hmac_len(hmac);
351   data_len = SILC_MESSAGE_DATALEN(data_len, mac_len + iv_len);
352
353   /* Calculate length of padding. IV is not included into the calculation
354      since it is not encrypted. */
355   pad_len = SILC_MESSAGE_PAD(6 + data_len);
356
357   /* Generate padding */
358   if (cipher) {
359     if (rng) {
360       for (i = 0; i < pad_len; i++) pad[i] = silc_rng_get_byte_fast(rng);
361     } else {
362       for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte_fast();
363     }
364   }
365
366   e.flags = flags;
367   e.public_key = public_key;
368   e.private_key = private_key;
369   e.hash = hash;
370   e.cipher = cipher;
371   e.hmac = hmac;
372   e.iv = iv_len ? iv : NULL;
373   e.payload_len = 6 + data_len + pad_len;
374
375   /* Encode the Message Payload */
376   if (silc_buffer_format(buffer,
377                          SILC_STR_UI_SHORT(flags),
378                          SILC_STR_UI_SHORT(data_len),
379                          SILC_STR_DATA(data, data_len),
380                          SILC_STR_UI_SHORT(pad_len),
381                          SILC_STR_DATA(pad, pad_len),
382                          SILC_STR_FUNC(silc_message_payload_encode_sig,
383                                        NULL, &e),
384                          SILC_STR_DATA(iv, iv_len),
385                          SILC_STR_FUNC(silc_message_payload_encode_encrypt,
386                                        NULL, &e),
387                          SILC_STR_END) < 0) {
388     silc_buffer_free(buf);
389     return NULL;
390   }
391
392   return buffer;
393 }
394
395 /* Free's Message Payload */
396
397 void silc_message_payload_free(SilcMessagePayload payload)
398 {
399   if (payload->data) {
400     memset(payload->data, 0, payload->data_len);
401     silc_free(payload->data);
402   }
403   if (payload->sig)
404     silc_message_signed_payload_free(payload->sig);
405   silc_free(payload->pad);
406   silc_free(payload);
407 }
408
409 /* Return flags */
410
411 SilcMessageFlags silc_message_get_flags(SilcMessagePayload payload)
412 {
413   return payload->flags;
414 }
415
416 /* Return data */
417
418 unsigned char *silc_message_get_data(SilcMessagePayload payload,
419                                      SilcUInt32 *data_len)
420 {
421   if (data_len)
422     *data_len = payload->data_len;
423   return payload->data;
424 }
425
426 /* Return MAC. The caller knows the length of the MAC */
427
428 unsigned char *silc_message_get_mac(SilcMessagePayload payload)
429 {
430   return payload->mac;
431 }
432
433 /* Return signature of the message */
434
435 SilcMessageSignedPayload
436 silc_message_get_signature(SilcMessagePayload payload)
437 {
438   return payload->sig;
439 }
440
441
442 /************************ Message Signature Payload *************************/
443
444 /* The SILC_MESSAGE_FLAG_SIGNED Payload */
445 struct SilcMessageSignedPayloadStruct {
446   SilcUInt16 pk_len;
447   SilcUInt16 pk_type;
448   SilcUInt16 sign_len;
449   unsigned char *pk_data;
450   unsigned char *sign_data;
451 };
452
453 /* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */
454
455 static SilcBuffer
456 silc_message_signed_encode_data(const unsigned char *message_payload,
457                                 SilcUInt32 message_payload_len,
458                                 unsigned char *pk,
459                                 SilcUInt32 pk_len, SilcUInt32 pk_type)
460 {
461   SilcBuffer sign;
462
463   sign = silc_buffer_alloc_size(message_payload_len + 4 + pk_len);
464   if (!sign)
465     return NULL;
466
467   silc_buffer_format(sign,
468                      SILC_STR_UI_XNSTRING(message_payload,
469                                           message_payload_len),
470                      SILC_STR_UI_SHORT(pk_len),
471                      SILC_STR_UI_SHORT(pk_type),
472                      SILC_STR_END);
473
474   if (pk && pk_len) {
475     silc_buffer_pull(sign, message_payload_len + 4);
476     silc_buffer_format(sign,
477                        SILC_STR_UI_XNSTRING(pk, pk_len),
478                        SILC_STR_END);
479     silc_buffer_push(sign, message_payload_len + 4);
480   }
481
482   return sign;
483 }
484
485 /* Parses the SILC_MESSAGE_FLAG_SIGNED Payload */
486
487 SilcMessageSignedPayload
488 silc_message_signed_payload_parse(const unsigned char *data,
489                                   SilcUInt32 data_len)
490 {
491   SilcMessageSignedPayload sig;
492   SilcBufferStruct buffer;
493   int ret;
494
495   SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload"));
496
497   SILC_LOG_HEXDUMP(("sig payload"), (unsigned char *)data, data_len);
498
499   silc_buffer_set(&buffer, (unsigned char *)data, data_len);
500   sig = silc_calloc(1, sizeof(*sig));
501   if (!sig)
502     return NULL;
503
504   /* Parse the payload */
505   ret = silc_buffer_unformat(&buffer,
506                              SILC_STR_UI_SHORT(&sig->pk_len),
507                              SILC_STR_UI_SHORT(&sig->pk_type),
508                              SILC_STR_END);
509   if (ret == -1 || sig->pk_len > data_len - 4) {
510     silc_message_signed_payload_free(sig);
511     SILC_LOG_DEBUG(("Malformed public key in SILC_MESSAGE_FLAG_SIGNED "
512                     "Payload"));
513     return NULL;
514   }
515
516   silc_buffer_pull(&buffer, 4);
517   ret = silc_buffer_unformat(&buffer,
518                              SILC_STR_UI_XNSTRING_ALLOC(&sig->pk_data,
519                                                         sig->pk_len),
520                              SILC_STR_UI16_NSTRING_ALLOC(&sig->sign_data,
521                                                          &sig->sign_len),
522                              SILC_STR_END);
523   if (ret == -1 || sig->sign_len > silc_buffer_len(&buffer) -
524       sig->pk_len - 2) {
525     silc_message_signed_payload_free(sig);
526     SILC_LOG_DEBUG(("Malformed SILC_MESSAGE_FLAG_SIGNED Payload"));
527     return NULL;
528   }
529   silc_buffer_push(&buffer, 4);
530
531   /* Signature must be provided */
532   if (sig->sign_len < 1)  {
533     SILC_LOG_DEBUG(("Malformed signature in SILC_MESSAGE_SIGNED_PAYLOAD "
534                     "Payload"));
535     silc_message_signed_payload_free(sig);
536     return NULL;
537   }
538
539   return sig;
540 }
541
542 /* Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the digital
543    signature. */
544
545 SilcBuffer
546 silc_message_signed_payload_encode(const unsigned char *message_payload,
547                                    SilcUInt32 message_payload_len,
548                                    SilcPublicKey public_key,
549                                    SilcPrivateKey private_key,
550                                    SilcHash hash)
551 {
552   SilcBuffer buffer, sign;
553   unsigned char auth_data[2048 + 1];
554   SilcUInt32 auth_len;
555   unsigned char *pk = NULL;
556   SilcUInt32 pk_len = 0;
557   SilcUInt16 pk_type;
558
559   if (!message_payload || !message_payload_len || !private_key || !hash)
560     return NULL;
561
562   if (public_key) {
563     pk = silc_pkcs_public_key_encode(public_key, &pk_len);
564     if (!pk)
565       return NULL;
566   }
567   pk_type = silc_pkcs_get_type(public_key);
568
569   /* Encode the data to be signed */
570   sign = silc_message_signed_encode_data(message_payload,
571                                          message_payload_len,
572                                          pk, pk_len, pk_type);
573   if (!sign) {
574     silc_free(pk);
575     return NULL;
576   }
577
578   /* Sign the buffer */
579
580   /* Compute the hash and the signature. */
581   if (!silc_pkcs_sign(private_key, sign->data, silc_buffer_len(sign),
582                       auth_data, sizeof(auth_data) - 1, &auth_len, hash)) {
583     SILC_LOG_ERROR(("Could not compute signature"));
584     silc_buffer_clear(sign);
585     silc_buffer_free(sign);
586     silc_free(pk);
587     return NULL;
588   }
589
590   /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */
591
592   buffer = silc_buffer_alloc_size(4 + pk_len + 2 + auth_len);
593   if (!buffer) {
594     silc_buffer_clear(sign);
595     silc_buffer_free(sign);
596     memset(auth_data, 0, sizeof(auth_data));
597     silc_free(pk);
598     return NULL;
599   }
600
601   silc_buffer_format(buffer,
602                      SILC_STR_UI_SHORT(pk_len),
603                      SILC_STR_UI_SHORT(pk_type),
604                      SILC_STR_END);
605
606   if (pk_len && pk) {
607     silc_buffer_pull(buffer, 4);
608     silc_buffer_format(buffer,
609                        SILC_STR_UI_XNSTRING(pk, pk_len),
610                        SILC_STR_END);
611     silc_buffer_push(buffer, 4);
612   }
613
614   silc_buffer_pull(buffer, 4 + pk_len);
615   silc_buffer_format(buffer,
616                      SILC_STR_UI_SHORT(auth_len),
617                      SILC_STR_UI_XNSTRING(auth_data, auth_len),
618                      SILC_STR_END);
619   silc_buffer_push(buffer, 4 + pk_len);
620
621   SILC_LOG_HEXDUMP(("sig payload"), buffer->data, silc_buffer_len(buffer));
622
623   memset(auth_data, 0, sizeof(auth_data));
624   silc_buffer_clear(sign);
625   silc_buffer_free(sign);
626   silc_free(pk);
627
628   return buffer;
629 }
630
631 /* Free the payload */
632
633 void silc_message_signed_payload_free(SilcMessageSignedPayload sig)
634 {
635   memset(sig->sign_data, 0, sig->sign_len);
636   silc_free(sig->sign_data);
637   silc_free(sig->pk_data);
638   silc_free(sig);
639 }
640
641 /* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
642
643 int silc_message_signed_verify(SilcMessageSignedPayload sig,
644                                SilcMessagePayload message,
645                                SilcPublicKey remote_public_key,
646                                SilcHash hash)
647 {
648   int ret = SILC_AUTH_FAILED;
649   SilcBuffer sign, 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, silc_buffer_len(tmp),
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   /* Verify the authentication data */
673   if (!silc_pkcs_verify(remote_public_key, sig->sign_data,
674                         sig->sign_len,
675                         sign->data, silc_buffer_len(sign), hash)) {
676
677     silc_buffer_clear(sign);
678     silc_buffer_free(sign);
679     SILC_LOG_DEBUG(("Signature verification failed"));
680     return ret;
681   }
682
683   ret = SILC_AUTH_OK;
684
685   silc_buffer_clear(sign);
686   silc_buffer_free(sign);
687
688   SILC_LOG_DEBUG(("Signature verification successful"));
689
690   return ret;
691 }
692
693 /* Return the public key from the payload */
694
695 SilcPublicKey
696 silc_message_signed_get_public_key(SilcMessageSignedPayload sig,
697                                    const unsigned char **pk_data,
698                                    SilcUInt32 *pk_data_len)
699 {
700   SilcPublicKey pk;
701
702   if (!sig->pk_data)
703     return NULL;
704
705   if (!silc_pkcs_public_key_alloc(sig->pk_type, sig->pk_data,
706                                   sig->pk_len, &pk))
707     return NULL;
708
709   if (pk_data)
710     *pk_data = sig->pk_data;
711   if (pk_data_len)
712     *pk_data_len = sig->pk_len;
713
714   return pk;
715 }