mpi: Extend the internal mpi_get_buffer.
authorWerner Koch <wk@gnupg.org>
Thu, 24 Jul 2014 14:16:53 +0000 (16:16 +0200)
committerWerner Koch <wk@gnupg.org>
Fri, 25 Jul 2014 06:13:56 +0000 (08:13 +0200)
* mpi/mpicoder.c (do_get_buffer): Add arg EXTRAALLOC.
(_gcry_mpi_get_buffer_extra): New.

mpi/mpicoder.c
src/mpi.h

index 58a4240..896dda1 100644 (file)
@@ -1,7 +1,7 @@
 /* mpicoder.c  -  Coder for the external representation of MPIs
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
  *               2008 Free Software Foundation, Inc.
- * Copyright (C) 2013 g10 Code GmbH
+ * Copyright (C) 2013, 2014 g10 Code GmbH
  *
  * This file is part of Libgcrypt.
  *
@@ -181,19 +181,27 @@ mpi_fromstr (gcry_mpi_t val, const char *str)
    returned value is stored as little endian and right padded with
    zeroes so that the returned buffer has at least FILL_LE bytes.
 
+   If EXTRAALLOC > 0 the returned buffer has these number of bytes
+   extra allocated at the end; if EXTRAALLOC < 0 the returned buffer
+   has the absolute value of EXTRAALLOC allocated at the begin of the
+   buffer (the are not initialized) and the MPI is stored right after
+   this.  This feature is useful to allow the caller to prefix the
+   returned value.  EXTRAALLOC is _not_ included in the value stored
+   at NBYTES.
+
    Caller must free the return string.  This function returns an
    allocated buffer with NBYTES set to zero if the value of A is zero.
    If sign is not NULL, it will be set to the sign of the A.  On error
    NULL is returned and ERRNO set appropriately.  */
 static unsigned char *
-do_get_buffer (gcry_mpi_t a, unsigned int fill_le,
+do_get_buffer (gcry_mpi_t a, unsigned int fill_le, int extraalloc,
                unsigned int *nbytes, int *sign, int force_secure)
 {
-  unsigned char *p, *buffer;
+  unsigned char *p, *buffer, *retbuffer;
   unsigned int length, tmp;
   mpi_limb_t alimb;
   int i;
-  size_t n;
+  size_t n, n2;
 
   if (sign)
     *sign = a->sign;
@@ -202,10 +210,20 @@ do_get_buffer (gcry_mpi_t a, unsigned int fill_le,
   n = *nbytes? *nbytes:1; /* Allocate at least one byte.  */
   if (n < fill_le)
     n = fill_le;
-  p = buffer = (force_secure || mpi_is_secure(a))? xtrymalloc_secure (n)
-                                                : xtrymalloc (n);
-  if (!buffer)
+  if (extraalloc < 0)
+    n2 = n + -extraalloc;
+  else
+    n2 = n + extraalloc;
+
+  retbuffer = (force_secure || mpi_is_secure(a))? xtrymalloc_secure (n2)
+                                                : xtrymalloc (n2);
+  if (!retbuffer)
     return NULL;
+  if (extraalloc < 0)
+    buffer = retbuffer + -extraalloc;
+  else
+    buffer = retbuffer;
+  p = buffer;
 
   for (i=a->nlimbs-1; i >= 0; i--)
     {
@@ -244,7 +262,7 @@ do_get_buffer (gcry_mpi_t a, unsigned int fill_le,
         *p++ = 0;
       *nbytes = length;
 
-      return buffer;
+      return retbuffer;
     }
 
   /* This is sub-optimal but we need to do the shift operation because
@@ -252,8 +270,8 @@ do_get_buffer (gcry_mpi_t a, unsigned int fill_le,
   for (p=buffer; *nbytes && !*p; p++, --*nbytes)
     ;
   if (p != buffer)
-    memmove (buffer,p, *nbytes);
-  return buffer;
+    memmove (buffer, p, *nbytes);
+  return retbuffer;
 }
 
 
@@ -261,14 +279,21 @@ byte *
 _gcry_mpi_get_buffer (gcry_mpi_t a, unsigned int fill_le,
                       unsigned int *r_nbytes, int *sign)
 {
-  return do_get_buffer (a, fill_le, r_nbytes, sign, 0);
+  return do_get_buffer (a, fill_le, 0, r_nbytes, sign, 0);
+}
+
+byte *
+_gcry_mpi_get_buffer_extra (gcry_mpi_t a, unsigned int fill_le, int extraalloc,
+                            unsigned int *r_nbytes, int *sign)
+{
+  return do_get_buffer (a, fill_le, extraalloc, r_nbytes, sign, 0);
 }
 
 byte *
 _gcry_mpi_get_secure_buffer (gcry_mpi_t a, unsigned int fill_le,
                              unsigned int *r_nbytes, int *sign)
 {
-  return do_get_buffer (a, fill_le, r_nbytes, sign, 1);
+  return do_get_buffer (a, fill_le, 0, r_nbytes, sign, 1);
 }
 
 
index 2479560..7407b7f 100644 (file)
--- a/src/mpi.h
+++ b/src/mpi.h
@@ -158,6 +158,9 @@ void  _gcry_log_mpidump( const char *text, gcry_mpi_t a );
 u32   _gcry_mpi_get_keyid( gcry_mpi_t a, u32 *keyid );
 byte *_gcry_mpi_get_buffer (gcry_mpi_t a, unsigned int fill_le,
                             unsigned int *r_nbytes, int *sign);
+byte *_gcry_mpi_get_buffer_extra (gcry_mpi_t a, unsigned int fill_le,
+                                  int extraalloc,
+                                  unsigned int *r_nbytes, int *sign);
 byte *_gcry_mpi_get_secure_buffer (gcry_mpi_t a, unsigned int fill_le,
                                    unsigned *r_nbytes, int *sign);
 void  _gcry_mpi_set_buffer ( gcry_mpi_t a, const void *buffer,