mpi: Add gcry_mpi_ec_curve_point.
[libgcrypt.git] / mpi / mpicoder.c
1 /* mpicoder.c  -  Coder for the external representation of MPIs
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
3  *               2008 Free Software Foundation, Inc.
4  * Copyright (C) 2013 g10 Code GmbH
5  *
6  * This file is part of Libgcrypt.
7  *
8  * Libgcrypt is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as
10  * published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * Libgcrypt 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 Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26
27 #include "mpi-internal.h"
28 #include "g10lib.h"
29
30 #define MAX_EXTERN_MPI_BITS 16384
31
32 /* Helper used to scan PGP style MPIs.  Returns NULL on failure. */
33 static gcry_mpi_t
34 mpi_read_from_buffer (const unsigned char *buffer, unsigned *ret_nread,
35                       int secure)
36 {
37   int i, j;
38   unsigned int nbits, nbytes, nlimbs, nread=0;
39   mpi_limb_t a;
40   gcry_mpi_t val = MPI_NULL;
41
42   if ( *ret_nread < 2 )
43     goto leave;
44   nbits = buffer[0] << 8 | buffer[1];
45   if ( nbits > MAX_EXTERN_MPI_BITS )
46     {
47 /*       log_debug ("mpi too large (%u bits)\n", nbits); */
48       goto leave;
49     }
50   buffer += 2;
51   nread = 2;
52
53   nbytes = (nbits+7) / 8;
54   nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
55   val = secure? mpi_alloc_secure (nlimbs) : mpi_alloc (nlimbs);
56   i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
57   i %= BYTES_PER_MPI_LIMB;
58   j= val->nlimbs = nlimbs;
59   val->sign = 0;
60   for ( ; j > 0; j-- )
61     {
62       a = 0;
63       for (; i < BYTES_PER_MPI_LIMB; i++ )
64         {
65           if ( ++nread > *ret_nread )
66             {
67 /*               log_debug ("mpi larger than buffer"); */
68               mpi_free (val);
69               val = NULL;
70               goto leave;
71             }
72           a <<= 8;
73           a |= *buffer++;
74         }
75       i = 0;
76       val->d[j-1] = a;
77     }
78
79  leave:
80   *ret_nread = nread;
81   return val;
82 }
83
84
85 /****************
86  * Fill the mpi VAL from the hex string in STR.
87  */
88 static int
89 mpi_fromstr (gcry_mpi_t val, const char *str)
90 {
91   int sign = 0;
92   int prepend_zero = 0;
93   int i, j, c, c1, c2;
94   unsigned int nbits, nbytes, nlimbs;
95   mpi_limb_t a;
96
97   if ( *str == '-' )
98     {
99       sign = 1;
100       str++;
101     }
102
103   /* Skip optional hex prefix.  */
104   if ( *str == '0' && str[1] == 'x' )
105     str += 2;
106
107   nbits = 4 * strlen (str);
108   if ((nbits % 8))
109     prepend_zero = 1;
110
111   nbytes = (nbits+7) / 8;
112   nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
113
114   if ( val->alloced < nlimbs )
115     mpi_resize (val, nlimbs);
116
117   i = BYTES_PER_MPI_LIMB - (nbytes % BYTES_PER_MPI_LIMB);
118   i %= BYTES_PER_MPI_LIMB;
119   j = val->nlimbs = nlimbs;
120   val->sign = sign;
121   for (; j > 0; j--)
122     {
123       a = 0;
124       for (; i < BYTES_PER_MPI_LIMB; i++)
125         {
126           if (prepend_zero)
127             {
128               c1 = '0';
129               prepend_zero = 0;
130             }
131           else
132             c1 = *str++;
133
134           if (!c1)
135             {
136               mpi_clear (val);
137               return 1;  /* Error.  */
138             }
139           c2 = *str++;
140           if (!c2)
141             {
142               mpi_clear (val);
143               return 1;  /* Error.  */
144             }
145           if ( c1 >= '0' && c1 <= '9' )
146             c = c1 - '0';
147           else if ( c1 >= 'a' && c1 <= 'f' )
148             c = c1 - 'a' + 10;
149           else if ( c1 >= 'A' && c1 <= 'F' )
150             c = c1 - 'A' + 10;
151           else
152             {
153               mpi_clear (val);
154               return 1;  /* Error.  */
155             }
156           c <<= 4;
157           if ( c2 >= '0' && c2 <= '9' )
158             c |= c2 - '0';
159           else if( c2 >= 'a' && c2 <= 'f' )
160             c |= c2 - 'a' + 10;
161           else if( c2 >= 'A' && c2 <= 'F' )
162             c |= c2 - 'A' + 10;
163           else
164             {
165               mpi_clear(val);
166               return 1;  /* Error. */
167             }
168           a <<= 8;
169           a |= c;
170         }
171       i = 0;
172       val->d[j-1] = a;
173     }
174
175   return 0;  /* Okay.  */
176 }
177
178
179 /* Dump the value of A in a format suitable for debugging to
180    Libgcrypt's logging stream.  Note that one leading space but no
181    trailing space or linefeed will be printed.  It is okay to pass
182    NULL for A.  Note that this function prints the sign as it is used
183    internally and won't map -0 to 0. */
184 void
185 gcry_mpi_dump (const gcry_mpi_t a)
186 {
187   int i;
188
189   log_printf (" ");
190   if (!a)
191     log_printf ("[MPI_NULL]");
192   else if (mpi_is_opaque (a))
193     {
194       unsigned int nbits;
195       const unsigned char *p;
196
197       p = gcry_mpi_get_opaque (a, &nbits);
198       log_printf ("[%u bit: ", nbits);
199       for (i=0; i < (nbits + 7)/8; i++)
200         log_printf ("%02x", p[i]);
201       log_printf ("]");
202     }
203   else
204     {
205       if (a->sign)
206         log_printf ( "-");
207 #if BYTES_PER_MPI_LIMB == 2
208 # define X "4"
209 #elif BYTES_PER_MPI_LIMB == 4
210 # define X "8"
211 #elif BYTES_PER_MPI_LIMB == 8
212 # define X "16"
213 #elif BYTES_PER_MPI_LIMB == 16
214 # define X "32"
215 #else
216 # error please define the format here
217 #endif
218       for (i=a->nlimbs; i > 0 ; i-- )
219         {
220           log_printf (i != a->nlimbs? "%0" X "lX":"%lX", (ulong)a->d[i-1]);
221         }
222 #undef X
223       if (!a->nlimbs)
224         log_printf ("0");
225     }
226 }
227
228 /* Convience function used internally. */
229 void
230 _gcry_log_mpidump (const char *text, gcry_mpi_t a)
231 {
232   log_printf ("%s:", text);
233   gcry_mpi_dump (a);
234   log_printf ("\n");
235 }
236
237
238 /* Return an allocated buffer with the MPI (msb first).  NBYTES
239    receives the length of this buffer.  Caller must free the return
240    string.  This function returns an allocated buffer with NBYTES set
241    to zero if the value of A is zero.  If sign is not NULL, it will be
242    set to the sign of the A.  On error NULL is returned and ERRNO set
243    appropriately.  */
244 static unsigned char *
245 do_get_buffer (gcry_mpi_t a, unsigned int *nbytes, int *sign, int force_secure)
246 {
247   unsigned char *p, *buffer;
248   mpi_limb_t alimb;
249   int i;
250   size_t n;
251
252   if (sign)
253     *sign = a->sign;
254
255   *nbytes = a->nlimbs * BYTES_PER_MPI_LIMB;
256   n = *nbytes? *nbytes:1; /* Allocate at least one byte.  */
257   p = buffer = (force_secure || mpi_is_secure(a))? gcry_malloc_secure (n)
258                                                  : gcry_malloc (n);
259   if (!buffer)
260     return NULL;
261
262   for (i=a->nlimbs-1; i >= 0; i--)
263     {
264       alimb = a->d[i];
265 #if BYTES_PER_MPI_LIMB == 4
266       *p++ = alimb >> 24;
267       *p++ = alimb >> 16;
268       *p++ = alimb >>  8;
269       *p++ = alimb        ;
270 #elif BYTES_PER_MPI_LIMB == 8
271       *p++ = alimb >> 56;
272       *p++ = alimb >> 48;
273       *p++ = alimb >> 40;
274       *p++ = alimb >> 32;
275       *p++ = alimb >> 24;
276       *p++ = alimb >> 16;
277       *p++ = alimb >>  8;
278       *p++ = alimb        ;
279 #else
280 #     error please implement for this limb size.
281 #endif
282     }
283
284   /* This is sub-optimal but we need to do the shift operation because
285      the caller has to free the returned buffer.  */
286   for (p=buffer; *nbytes && !*p; p++, --*nbytes)
287     ;
288   if (p != buffer)
289     memmove (buffer,p, *nbytes);
290   return buffer;
291 }
292
293
294 byte *
295 _gcry_mpi_get_buffer (gcry_mpi_t a, unsigned int *nbytes, int *sign)
296 {
297   return do_get_buffer (a, nbytes, sign, 0);
298 }
299
300 byte *
301 _gcry_mpi_get_secure_buffer (gcry_mpi_t a, unsigned *nbytes, int *sign)
302 {
303   return do_get_buffer (a, nbytes, sign, 1);
304 }
305
306
307 /*
308  * Use the NBYTES at BUFFER_ARG to update A.  Set the sign of a to
309  * SIGN.
310  */
311 void
312 _gcry_mpi_set_buffer (gcry_mpi_t a, const void *buffer_arg,
313                       unsigned int nbytes, int sign)
314 {
315   const unsigned char *buffer = (const unsigned char*)buffer_arg;
316   const unsigned char *p;
317   mpi_limb_t alimb;
318   int nlimbs;
319   int i;
320
321   if (mpi_is_immutable (a))
322     {
323       mpi_immutable_failed ();
324       return;
325     }
326
327   nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
328   RESIZE_IF_NEEDED(a, nlimbs);
329   a->sign = sign;
330
331   for (i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; )
332     {
333 #if BYTES_PER_MPI_LIMB == 4
334       alimb  = *p--         ;
335       alimb |= *p-- <<  8 ;
336       alimb |= *p-- << 16 ;
337       alimb |= *p-- << 24 ;
338 #elif BYTES_PER_MPI_LIMB == 8
339       alimb  = (mpi_limb_t)*p-- ;
340       alimb |= (mpi_limb_t)*p-- <<  8 ;
341       alimb |= (mpi_limb_t)*p-- << 16 ;
342       alimb |= (mpi_limb_t)*p-- << 24 ;
343       alimb |= (mpi_limb_t)*p-- << 32 ;
344       alimb |= (mpi_limb_t)*p-- << 40 ;
345       alimb |= (mpi_limb_t)*p-- << 48 ;
346       alimb |= (mpi_limb_t)*p-- << 56 ;
347 #else
348 #       error please implement for this limb size.
349 #endif
350       a->d[i++] = alimb;
351     }
352   if ( p >= buffer )
353     {
354 #if BYTES_PER_MPI_LIMB == 4
355       alimb  = *p--;
356       if (p >= buffer)
357         alimb |= *p-- <<  8;
358       if (p >= buffer)
359         alimb |= *p-- << 16;
360       if (p >= buffer)
361         alimb |= *p-- << 24;
362 #elif BYTES_PER_MPI_LIMB == 8
363       alimb  = (mpi_limb_t)*p--;
364       if (p >= buffer)
365         alimb |= (mpi_limb_t)*p-- << 8;
366       if (p >= buffer)
367         alimb |= (mpi_limb_t)*p-- << 16;
368       if (p >= buffer)
369         alimb |= (mpi_limb_t)*p-- << 24;
370       if (p >= buffer)
371         alimb |= (mpi_limb_t)*p-- << 32;
372       if (p >= buffer)
373         alimb |= (mpi_limb_t)*p-- << 40;
374       if (p >= buffer)
375         alimb |= (mpi_limb_t)*p-- << 48;
376       if (p >= buffer)
377         alimb |= (mpi_limb_t)*p-- << 56;
378 #else
379 #     error please implement for this limb size.
380 #endif
381       a->d[i++] = alimb;
382     }
383   a->nlimbs = i;
384   gcry_assert (i == nlimbs);
385 }
386
387
388 /* Convert the external representation of an integer stored in BUFFER
389    with a length of BUFLEN into a newly create MPI returned in
390    RET_MPI.  If NBYTES is not NULL, it will receive the number of
391    bytes actually scanned after a successful operation.  */
392 gcry_error_t
393 gcry_mpi_scan (struct gcry_mpi **ret_mpi, enum gcry_mpi_format format,
394                const void *buffer_arg, size_t buflen, size_t *nscanned)
395 {
396   const unsigned char *buffer = (const unsigned char*)buffer_arg;
397   struct gcry_mpi *a = NULL;
398   unsigned int len;
399   int secure = (buffer && gcry_is_secure (buffer));
400
401   if (format == GCRYMPI_FMT_SSH)
402     len = 0;
403   else
404     len = buflen;
405
406   if (format == GCRYMPI_FMT_STD)
407     {
408       const unsigned char *s = buffer;
409
410       a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1)
411                                     /BYTES_PER_MPI_LIMB)
412                 : mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB);
413       if (len)
414         {
415           a->sign = !!(*s & 0x80);
416           if (a->sign)
417             {
418               /* FIXME: we have to convert from 2compl to magnitude format */
419               mpi_free (a);
420               return gcry_error (GPG_ERR_INTERNAL);
421             }
422           else
423             _gcry_mpi_set_buffer (a, s, len, 0);
424         }
425       if (ret_mpi)
426         {
427           mpi_normalize ( a );
428           *ret_mpi = a;
429         }
430       else
431         mpi_free(a);
432       return 0;
433     }
434   else if (format == GCRYMPI_FMT_USG)
435     {
436       a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1)
437                                     /BYTES_PER_MPI_LIMB)
438                 : mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB);
439
440       if (len)
441         _gcry_mpi_set_buffer (a, buffer, len, 0);
442       if (ret_mpi)
443         {
444           mpi_normalize ( a );
445           *ret_mpi = a;
446         }
447       else
448         mpi_free(a);
449       return 0;
450     }
451   else if (format == GCRYMPI_FMT_PGP)
452     {
453       a = mpi_read_from_buffer (buffer, &len, secure);
454       if (nscanned)
455         *nscanned = len;
456       if (ret_mpi && a)
457         {
458           mpi_normalize (a);
459           *ret_mpi = a;
460         }
461       else if (a)
462         {
463           mpi_free(a);
464           a = NULL;
465         }
466       return a? 0 : gcry_error (GPG_ERR_INV_OBJ);
467     }
468   else if (format == GCRYMPI_FMT_SSH)
469     {
470       const unsigned char *s = buffer;
471       size_t n;
472
473       /* This test is not strictly necessary and an assert (!len)
474          would be sufficient.  We keep this test in case we later
475          allow the BUFLEN argument to act as a sanitiy check.  Same
476          below. */
477       if (len && len < 4)
478         return gcry_error (GPG_ERR_TOO_SHORT);
479
480       n = (s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
481       s += 4;
482       if (len)
483         len -= 4;
484       if (len && n > len)
485         return gcry_error (GPG_ERR_TOO_LARGE);
486
487       a = secure? mpi_alloc_secure ((n+BYTES_PER_MPI_LIMB-1)
488                                     /BYTES_PER_MPI_LIMB)
489                 : mpi_alloc ((n+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB);
490       if (n)
491         {
492           a->sign = !!(*s & 0x80);
493           if (a->sign)
494             {
495               /* FIXME: we have to convert from 2compl to magnitude format */
496               mpi_free(a);
497               return gcry_error (GPG_ERR_INTERNAL);
498             }
499           else
500             _gcry_mpi_set_buffer( a, s, n, 0 );
501         }
502       if (nscanned)
503         *nscanned = n+4;
504       if (ret_mpi)
505         {
506           mpi_normalize ( a );
507           *ret_mpi = a;
508         }
509       else
510         mpi_free(a);
511       return 0;
512     }
513   else if (format == GCRYMPI_FMT_HEX)
514     {
515       /* We can only handle C strings for now.  */
516       if (buflen)
517         return gcry_error (GPG_ERR_INV_ARG);
518
519       a = secure? mpi_alloc_secure (0) : mpi_alloc(0);
520       if (mpi_fromstr (a, (const char *)buffer))
521         {
522           mpi_free (a);
523           return gcry_error (GPG_ERR_INV_OBJ);
524         }
525       if (ret_mpi)
526         {
527           mpi_normalize ( a );
528           *ret_mpi = a;
529         }
530       else
531         mpi_free(a);
532       return 0;
533     }
534   else
535     return gcry_error (GPG_ERR_INV_ARG);
536 }
537
538
539 /* Convert the big integer A into the external representation
540    described by FORMAT and store it in the provided BUFFER which has
541    been allocated by the user with a size of BUFLEN bytes.  NWRITTEN
542    receives the actual length of the external representation unless it
543    has been passed as NULL.  BUFFER may be NULL to query the required
544    length.  */
545 gcry_error_t
546 gcry_mpi_print (enum gcry_mpi_format format,
547                 unsigned char *buffer, size_t buflen,
548                 size_t *nwritten, struct gcry_mpi *a)
549 {
550   unsigned int nbits = mpi_get_nbits (a);
551   size_t len;
552   size_t dummy_nwritten;
553   int negative;
554
555   if (!nwritten)
556     nwritten = &dummy_nwritten;
557
558   /* Libgcrypt does no always care to set clear the sign if the value
559      is 0.  For printing this is a bit of a surprise, in particular
560      because if some of the formats don't support negative numbers but
561      should be able to print a zero.  Thus we need this extra test
562      for a negative number.  */
563   if (a->sign && _gcry_mpi_cmp_ui (a, 0))
564     negative = 1;
565   else
566     negative = 0;
567
568   len = buflen;
569   *nwritten = 0;
570   if (format == GCRYMPI_FMT_STD)
571     {
572       unsigned char *tmp;
573       int extra = 0;
574       unsigned int n;
575
576       if (negative)
577         return gcry_error (GPG_ERR_INTERNAL); /* Can't handle it yet. */
578
579       tmp = _gcry_mpi_get_buffer (a, &n, NULL);
580       if (!tmp)
581         return gpg_error_from_syserror ();
582
583       /* If the high bit of the returned buffer is set, we need to
584          print an extra leading 0x00 so that the output is interpreted
585          as a positive number.  */
586       if (n && (*tmp & 0x80))
587         {
588           n++;
589           extra = 1;
590         }
591
592       if (buffer && n > len)
593         {
594           /* The provided buffer is too short. */
595           gcry_free (tmp);
596           return gcry_error (GPG_ERR_TOO_SHORT);
597         }
598       if (buffer)
599         {
600           unsigned char *s = buffer;
601
602           if (extra)
603             *s++ = 0;
604           memcpy (s, tmp, n-extra);
605         }
606       gcry_free(tmp);
607       *nwritten = n;
608       return 0;
609     }
610   else if (format == GCRYMPI_FMT_USG)
611     {
612       unsigned int n = (nbits + 7)/8;
613
614       /* Note:  We ignore the sign for this format.  */
615       /* FIXME: for performance reasons we should put this into
616          mpi_aprint because we can then use the buffer directly.  */
617
618       if (buffer && n > len)
619         return gcry_error (GPG_ERR_TOO_SHORT);
620       if (buffer)
621         {
622           unsigned char *tmp;
623
624           tmp = _gcry_mpi_get_buffer (a, &n, NULL);
625           if (!tmp)
626             return gpg_error_from_syserror ();
627           memcpy (buffer, tmp, n);
628           gcry_free (tmp);
629         }
630       *nwritten = n;
631       return 0;
632     }
633   else if (format == GCRYMPI_FMT_PGP)
634     {
635       unsigned int n = (nbits + 7)/8;
636
637       /* The PGP format can only handle unsigned integers.  */
638       if (negative)
639         return gcry_error (GPG_ERR_INV_ARG);
640
641       if (buffer && n+2 > len)
642         return gcry_error (GPG_ERR_TOO_SHORT);
643
644       if (buffer)
645         {
646           unsigned char *tmp;
647           unsigned char *s = buffer;
648
649           s[0] = nbits >> 8;
650           s[1] = nbits;
651
652           tmp = _gcry_mpi_get_buffer (a, &n, NULL);
653           if (!tmp)
654             return gpg_error_from_syserror ();
655           memcpy (s+2, tmp, n);
656           gcry_free (tmp);
657         }
658       *nwritten = n+2;
659       return 0;
660     }
661   else if (format == GCRYMPI_FMT_SSH)
662     {
663       unsigned char *tmp;
664       int extra = 0;
665       unsigned int n;
666
667       if (negative)
668         return gcry_error (GPG_ERR_INTERNAL); /* Can't handle it yet.  */
669
670       tmp = _gcry_mpi_get_buffer (a, &n, NULL);
671       if (!tmp)
672         return gpg_error_from_syserror ();
673       if (n && (*tmp & 0x80))
674         {
675           n++;
676           extra=1;
677         }
678
679       if (buffer && n+4 > len)
680         {
681           gcry_free(tmp);
682           return gcry_error (GPG_ERR_TOO_SHORT);
683         }
684
685       if (buffer)
686         {
687           unsigned char *s = buffer;
688
689           *s++ = n >> 24;
690           *s++ = n >> 16;
691           *s++ = n >> 8;
692           *s++ = n;
693           if (extra)
694             *s++ = 0;
695
696           memcpy (s, tmp, n-extra);
697         }
698       gcry_free (tmp);
699       *nwritten = 4+n;
700       return 0;
701     }
702   else if (format == GCRYMPI_FMT_HEX)
703     {
704       unsigned char *tmp;
705       int i;
706       int extra = 0;
707       unsigned int n = 0;
708
709       tmp = _gcry_mpi_get_buffer (a, &n, NULL);
710       if (!tmp)
711         return gpg_error_from_syserror ();
712       if (!n || (*tmp & 0x80))
713         extra = 2;
714
715       if (buffer && 2*n + extra + negative + 1 > len)
716         {
717           gcry_free(tmp);
718           return gcry_error (GPG_ERR_TOO_SHORT);
719         }
720       if (buffer)
721         {
722           unsigned char *s = buffer;
723
724           if (negative)
725             *s++ = '-';
726           if (extra)
727             {
728               *s++ = '0';
729               *s++ = '0';
730             }
731
732           for (i=0; i < n; i++)
733             {
734               unsigned int c = tmp[i];
735
736               *s++ = (c >> 4) < 10? '0'+(c>>4) : 'A'+(c>>4)-10 ;
737               c &= 15;
738               *s++ = c < 10? '0'+c : 'A'+c-10 ;
739             }
740           *s++ = 0;
741           *nwritten = s - buffer;
742         }
743       else
744         {
745           *nwritten = 2*n + extra + negative + 1;
746         }
747       gcry_free (tmp);
748       return 0;
749     }
750   else
751     return gcry_error (GPG_ERR_INV_ARG);
752 }
753
754
755 /*
756  * Like gcry_mpi_print but this function allocates the buffer itself.
757  * The caller has to supply the address of a pointer.  NWRITTEN may be
758  * NULL.
759  */
760 gcry_error_t
761 gcry_mpi_aprint (enum gcry_mpi_format format,
762                  unsigned char **buffer, size_t *nwritten,
763                  struct gcry_mpi *a)
764 {
765   size_t n;
766   gcry_error_t rc;
767
768   *buffer = NULL;
769   rc = gcry_mpi_print (format, NULL, 0, &n, a);
770   if (rc)
771     return rc;
772
773   *buffer = mpi_is_secure(a) ? gcry_malloc_secure (n?n:1) : gcry_malloc (n?n:1);
774   if (!*buffer)
775     return gpg_error_from_syserror ();
776   rc = gcry_mpi_print( format, *buffer, n, &n, a );
777   if (rc)
778     {
779       gcry_free(*buffer);
780       *buffer = NULL;
781     }
782   else if (nwritten)
783     *nwritten = n;
784   return rc;
785 }