~ubuntu-branches/ubuntu/natty/libgcrypt11/natty-proposed

« back to all changes in this revision

Viewing changes to mpi/mpicoder.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Metzler
  • Date: 2009-02-21 13:46:58 UTC
  • mto: (1.1.6 upstream) (2.1.3 squeeze)
  • mto: This revision was merged to the branch mainline in revision 18.
  • Revision ID: james.westby@ubuntu.com-20090221134658-855twvcr4ezk2ron
ImportĀ upstreamĀ versionĀ 1.4.4

Show diffs side-by-side

added added

removed removed

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