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