~henrik-ziegeldorf/hipl/pisa

« back to all changes in this revision

Viewing changes to linux/net/ipv6/hip/crypto/mpicoder.c

  • Committer: Kristian Slavov
  • Date: 2004-02-11 16:00:58 UTC
  • Revision ID: Arch-1:hipl@gaijin.tky.hut.fi--hipl%hipl--main--2.6--patch-4
Added the rest of the HIPL components to the source tree. Does not compile.
The rest of the components were taken from hipl--main--1.0--patch-40.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* mpicoder.c  -  Coder for the external representation of MPIs
 
2
 * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
3
 *
 
4
 * This file is part of Libgcrypt.
 
5
 *
 
6
 * Libgcrypt is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU Lesser General Public License as
 
8
 * published by the Free Software Foundation; either version 2.1 of
 
9
 * the License, or (at your option) any later version.
 
10
 *
 
11
 * Libgcrypt is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU Lesser General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU Lesser General Public
 
17
 * License along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
19
 */
 
20
 
 
21
/*#include <config.h>
 
22
#include <stdio.h>
 
23
#include <string.h>
 
24
#include <stdlib.h>
 
25
#include <assert.h>
 
26
*/
 
27
#include "kernel-interface.h"
 
28
 
 
29
#define MAX_EXTERN_MPI_BITS 16384
 
30
 
 
31
 
 
32
#if 0
 
33
static MPI
 
34
mpi_read_from_buffer(byte *buffer, unsigned *ret_nread, int secure)
 
35
{
 
36
    int i, j;
 
37
    unsigned int nbits, nbytes, nlimbs, nread=0;
 
38
    mpi_limb_t a;
 
39
    MPI val = MPI_NULL;
 
40
 
 
41
    if( *ret_nread < 2 )
 
42
        goto leave;
 
43
    nbits = buffer[0] << 8 | buffer[1];
 
44
    if( nbits > MAX_EXTERN_MPI_BITS ) {
 
45
        log_error("mpi too large (%u bits)\n", nbits);
 
46
        goto leave;
 
47
    }
 
48
    else if( !nbits ) {
 
49
        log_error("an mpi of size 0 is not allowed\n");
 
50
        goto leave;
 
51
    }
 
52
    buffer += 2;
 
53
    nread = 2;
 
54
 
 
55
    nbytes = (nbits+7) / 8;
 
56
    nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
 
57
    val = secure? mpi_alloc_secure( nlimbs )
 
58
                : mpi_alloc( nlimbs );
 
59
    i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
 
60
    i %= BYTES_PER_MPI_LIMB;
 
61
    j= val->nlimbs = nlimbs;
 
62
    val->sign = 0;
 
63
    for( ; j > 0; j-- ) {
 
64
        a = 0;
 
65
        for(; i < BYTES_PER_MPI_LIMB; i++ ) {
 
66
            if( ++nread > *ret_nread )
 
67
                log_bug("mpi larger than buffer");
 
68
            a <<= 8;
 
69
            a |= *buffer++;
 
70
        }
 
71
        i = 0;
 
72
        val->d[j-1] = a;
 
73
    }
 
74
 
 
75
  leave:
 
76
    *ret_nread = nread;
 
77
    return val;
 
78
}
 
79
#endif
 
80
 
 
81
/****************
 
82
 * Make an mpi from a hex character string.
 
83
 */
 
84
static int
 
85
mpi_fromstr(MPI val, const char *str)
 
86
{
 
87
    int sign=0, prepend_zero=0, i, j, c, c1, c2;
 
88
    unsigned nbits, nbytes, nlimbs;
 
89
    mpi_limb_t a;
 
90
 
 
91
    if( *str == '-' ) {
 
92
        sign = 1;
 
93
        str++;
 
94
    }
 
95
 
 
96
    /* skip optional hex prefix */
 
97
    if ( *str == '0' && str[1] == 'x' ) {
 
98
        str += 2;
 
99
    }
 
100
 
 
101
    nbits = strlen(str)*4;
 
102
    if( nbits % 8 )
 
103
        prepend_zero = 1;
 
104
    nbytes = (nbits+7) / 8;
 
105
    nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
 
106
    if( val->alloced < nlimbs )
 
107
        mpi_resize(val, nlimbs );
 
108
    i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
 
109
    i %= BYTES_PER_MPI_LIMB;
 
110
    j= val->nlimbs = nlimbs;
 
111
    val->sign = sign;
 
112
    for( ; j > 0; j-- ) {
 
113
        a = 0;
 
114
        for(; i < BYTES_PER_MPI_LIMB; i++ ) {
 
115
            if( prepend_zero ) {
 
116
                c1 = '0';
 
117
                prepend_zero = 0;
 
118
            }
 
119
            else
 
120
                c1 = *str++;
 
121
//          assert(c1);
 
122
            c2 = *str++;
 
123
//          assert(c2);
 
124
            if( c1 >= '0' && c1 <= '9' )
 
125
                c = c1 - '0';
 
126
            else if( c1 >= 'a' && c1 <= 'f' )
 
127
                c = c1 - 'a' + 10;
 
128
            else if( c1 >= 'A' && c1 <= 'F' )
 
129
                c = c1 - 'A' + 10;
 
130
            else {
 
131
                mpi_clear(val);
 
132
                return 1;
 
133
            }
 
134
            c <<= 4;
 
135
            if( c2 >= '0' && c2 <= '9' )
 
136
                c |= c2 - '0';
 
137
            else if( c2 >= 'a' && c2 <= 'f' )
 
138
                c |= c2 - 'a' + 10;
 
139
            else if( c2 >= 'A' && c2 <= 'F' )
 
140
                c |= c2 - 'A' + 10;
 
141
            else {
 
142
                mpi_clear(val);
 
143
                return 1;
 
144
            }
 
145
            a <<= 8;
 
146
            a |= c;
 
147
        }
 
148
        i = 0;
 
149
        val->d[j-1] = a;
 
150
    }
 
151
 
 
152
    return 0;
 
153
}
 
154
 
 
155
 
 
156
/****************
 
157
 * print an MPI to the given stream and return the number of characters
 
158
 * printed.
 
159
 * FIXME: Replace this by the more generic gcry_mpi_print()
 
160
 */
 
161
#if 0
 
162
static int
 
163
mpi_print( FILE *fp, MPI a, int mode )
 
164
{
 
165
    int i, n=0;
 
166
 
 
167
    if( a == MPI_NULL )
 
168
        return fprintf(fp, "[MPI_NULL]");
 
169
    if( !mode ) {
 
170
        unsigned int n1;
 
171
        n1 = mpi_get_nbits(a);
 
172
        n += fprintf(fp, "[%u bits]", n1);
 
173
    }
 
174
    else {
 
175
        if( a->sign )
 
176
            putc('-', fp);
 
177
       #if BYTES_PER_MPI_LIMB == 2
 
178
          #define X "4"
 
179
       #elif BYTES_PER_MPI_LIMB == 4
 
180
          #define X "8"
 
181
       #elif BYTES_PER_MPI_LIMB == 8
 
182
          #define X "16"
 
183
       #else
 
184
          #error please define the format here
 
185
       #endif
 
186
        for(i=a->nlimbs; i > 0 ; i-- ) {
 
187
            n += fprintf(fp, i!=a->nlimbs? "%0" X "lX":"%lX", (ulong)a->d[i-1]);
 
188
       #undef X
 
189
        }
 
190
        if( !a->nlimbs )
 
191
            putc('0', fp );
 
192
    }
 
193
    return n;
 
194
}
 
195
#endif
 
196
 
 
197
#if 0
 
198
#if __GNUC__ >= 2
 
199
#warning We should move this function to elsewhere
 
200
#endif
 
201
void
 
202
_gcry_log_mpidump( const char *text, MPI a )
 
203
{
 
204
    FILE *fp = stderr; /* used to be log_stream() */
 
205
 
 
206
    /* FIXME: Replace this function by a g10_log_xxx one */
 
207
    fprintf(fp,"%s: ",text);
 
208
    mpi_print(fp, a, 1 );
 
209
    fputc('\n', fp);
 
210
}
 
211
 
 
212
#endif
 
213
 
 
214
/****************
 
215
 * Return an m_alloced buffer with the MPI (msb first).
 
216
 * NBYTES receives the length of this buffer. Caller must free the
 
217
 * return string (This function does return a 0 byte buffer with NBYTES
 
218
 * set to zero if the value of A is zero. If sign is not NULL, it will
 
219
 * be set to the sign of the A.
 
220
 */
 
221
static byte *
 
222
do_get_buffer( MPI a, unsigned *nbytes, int *sign, int force_secure )
 
223
{
 
224
    byte *p, *buffer;
 
225
    mpi_limb_t alimb;
 
226
    int i;
 
227
    size_t n;
 
228
 
 
229
    if( sign )
 
230
        *sign = a->sign;
 
231
    *nbytes = a->nlimbs * BYTES_PER_MPI_LIMB;
 
232
    n = *nbytes? *nbytes:1; /* allocate at least one byte */
 
233
    p = buffer = force_secure || mpi_is_secure(a) ? gcry_xmalloc_secure(n)
 
234
                                                  : gcry_xmalloc(n);
 
235
 
 
236
    for(i=a->nlimbs-1; i >= 0; i-- ) {
 
237
        alimb = a->d[i];
 
238
      #if BYTES_PER_MPI_LIMB == 4
 
239
        *p++ = alimb >> 24;
 
240
        *p++ = alimb >> 16;
 
241
        *p++ = alimb >>  8;
 
242
        *p++ = alimb      ;
 
243
      #elif BYTES_PER_MPI_LIMB == 8
 
244
        *p++ = alimb >> 56;
 
245
        *p++ = alimb >> 48;
 
246
        *p++ = alimb >> 40;
 
247
        *p++ = alimb >> 32;
 
248
        *p++ = alimb >> 24;
 
249
        *p++ = alimb >> 16;
 
250
        *p++ = alimb >>  8;
 
251
        *p++ = alimb      ;
 
252
      #else
 
253
        #error please implement for this limb size.
 
254
      #endif
 
255
    }
 
256
 
 
257
    /* this is sub-optimal but we need to do the shift oepration because
 
258
     * the caller has to free the returned buffer */
 
259
    for(p=buffer; !*p && *nbytes; p++, --*nbytes )
 
260
        ;
 
261
    if( p != buffer )
 
262
        memmove(buffer,p, *nbytes);
 
263
    return buffer;
 
264
}
 
265
 
 
266
 
 
267
byte *
 
268
_gcry_mpi_get_buffer( MPI a, unsigned *nbytes, int *sign )
 
269
{
 
270
    return do_get_buffer( a, nbytes, sign, 0 );
 
271
}
 
272
 
 
273
byte *
 
274
_gcry_mpi_get_secure_buffer( MPI a, unsigned *nbytes, int *sign )
 
275
{
 
276
    return do_get_buffer( a, nbytes, sign, 1 );
 
277
}
 
278
 
 
279
/****************
 
280
 * Use BUFFER to update MPI.
 
281
 */
 
282
void
 
283
_gcry_mpi_set_buffer( MPI a, const byte *buffer, unsigned nbytes, int sign )
 
284
{
 
285
    const byte *p;
 
286
    mpi_limb_t alimb;
 
287
    int nlimbs;
 
288
    int i;
 
289
 
 
290
    nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
 
291
    RESIZE_IF_NEEDED(a, nlimbs);
 
292
    a->sign = sign;
 
293
 
 
294
    for(i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; ) {
 
295
#if BYTES_PER_MPI_LIMB == 4
 
296
        alimb  = *p--       ;
 
297
        alimb |= *p-- <<  8 ;
 
298
        alimb |= *p-- << 16 ;
 
299
        alimb |= *p-- << 24 ;
 
300
#elif BYTES_PER_MPI_LIMB == 8
 
301
        alimb  = (mpi_limb_t)*p--       ;
 
302
        alimb |= (mpi_limb_t)*p-- <<  8 ;
 
303
        alimb |= (mpi_limb_t)*p-- << 16 ;
 
304
        alimb |= (mpi_limb_t)*p-- << 24 ;
 
305
        alimb |= (mpi_limb_t)*p-- << 32 ;
 
306
        alimb |= (mpi_limb_t)*p-- << 40 ;
 
307
        alimb |= (mpi_limb_t)*p-- << 48 ;
 
308
        alimb |= (mpi_limb_t)*p-- << 56 ;
 
309
#else
 
310
#error please implement for this limb size.
 
311
#endif
 
312
        a->d[i++] = alimb;
 
313
    }
 
314
    if( p >= buffer ) {
 
315
#if BYTES_PER_MPI_LIMB == 4
 
316
        alimb  = *p--       ;
 
317
        if( p >= buffer ) alimb |= *p-- <<  8 ;
 
318
        if( p >= buffer ) alimb |= *p-- << 16 ;
 
319
        if( p >= buffer ) alimb |= *p-- << 24 ;
 
320
#elif BYTES_PER_MPI_LIMB == 8
 
321
        alimb  = (mpi_limb_t)*p-- ;
 
322
        if( p >= buffer ) alimb |= (mpi_limb_t)*p-- <<  8 ;
 
323
        if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 16 ;
 
324
        if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 24 ;
 
325
        if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 32 ;
 
326
        if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 40 ;
 
327
        if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 48 ;
 
328
        if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 56 ;
 
329
#else
 
330
#error please implement for this limb size.
 
331
#endif
 
332
        a->d[i++] = alimb;
 
333
    }
 
334
    a->nlimbs = i;
 
335
//    assert( i == nlimbs );
 
336
}
 
337
 
 
338
 
 
339
 
 
340
int
 
341
gcry_mpi_scan( struct gcry_mpi **ret_mpi, enum gcry_mpi_format format,
 
342
                const char *buffer, size_t *nbytes )
 
343
{
 
344
    struct gcry_mpi *a = NULL;
 
345
    unsigned int len;
 
346
 
 
347
    
 
348
    len = nbytes? *nbytes : (format == GCRYMPI_FMT_SSH? 0 : strlen(buffer));
 
349
 
 
350
#if 0
 
351
    /* TODO: add a way to allocate the MPI in secure memory
 
352
     * Hmmm: maybe it is better to retrieve this information from
 
353
     * the provided buffer. */
 
354
#if __GNUC__ >= 2
 
355
#warning secure memory is not used here.
 
356
#endif
 
357
#endif
 
358
    if( format == GCRYMPI_FMT_STD ) {
 
359
        const byte *s = buffer;
 
360
 
 
361
        a = mpi_alloc( (len+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB );
 
362
        if( len ) { /* not zero */
 
363
            a->sign = *s & 0x80;
 
364
            if( a->sign ) {
 
365
                /* FIXME: we have to convert from 2compl to magnitude format */
 
366
                mpi_free(a);
 
367
                return GCRYERR_INTERNAL;
 
368
            }
 
369
            else
 
370
                _gcry_mpi_set_buffer( a, s, len, 0 );
 
371
        }
 
372
        if( ret_mpi ) {
 
373
            mpi_normalize ( a );
 
374
            *ret_mpi = a;
 
375
        }
 
376
        else
 
377
            mpi_free(a);
 
378
        return 0;
 
379
    }
 
380
 
 
381
    else if( format == GCRYMPI_FMT_USG ) {
 
382
        a = mpi_alloc( (len+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB );
 
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 0;
 
392
    }
 
393
#if 0
 
394
    else if( format == GCRYMPI_FMT_PGP ) {
 
395
        a = mpi_read_from_buffer( (char*)buffer, &len, 0 );
 
396
        if( nbytes )
 
397
            *nbytes = len;
 
398
        if( ret_mpi && a ) {
 
399
            mpi_normalize ( a );
 
400
            *ret_mpi = a;
 
401
        }
 
402
        else
 
403
            mpi_free(a);
 
404
        return a? 0 : GCRYERR_INV_OBJ;
 
405
    }
 
406
    else if( format == GCRYMPI_FMT_SSH ) {
 
407
        const byte *s = buffer;
 
408
        size_t n;
 
409
 
 
410
        if( len && len < 4 )
 
411
            return GCRYERR_TOO_SHORT;
 
412
        n = s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
 
413
        s += 4; 
 
414
        if (len)
 
415
          len -= 4;
 
416
        if( len && n > len )
 
417
            return GCRYERR_TOO_LARGE; /* or should it be too_short */
 
418
 
 
419
        a = mpi_alloc( (n+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB );
 
420
        if( n ) { /* not zero */
 
421
            a->sign = *s & 0x80;
 
422
            if( a->sign ) {
 
423
                /* FIXME: we have to convert from 2compl to magnitude format */
 
424
                mpi_free(a);
 
425
                return GCRYERR_INTERNAL;
 
426
            }
 
427
            else
 
428
                _gcry_mpi_set_buffer( a, s, n, 0 );
 
429
        }
 
430
        if( nbytes )
 
431
            *nbytes = n+4;
 
432
        if( ret_mpi ) {
 
433
            mpi_normalize ( a );
 
434
            *ret_mpi = a;
 
435
        }
 
436
        else
 
437
            mpi_free(a);
 
438
        return 0;
 
439
    }
 
440
#endif /* 0 */
 
441
    else if( format == GCRYMPI_FMT_HEX ) {
 
442
        if( nbytes )
 
443
            return GCRYERR_INV_ARG; /* can only handle C strings for now */
 
444
        a = mpi_alloc(0);
 
445
        if( mpi_fromstr( a, buffer ) )
 
446
            return GCRYERR_INV_OBJ;
 
447
        if( ret_mpi ) {
 
448
            mpi_normalize ( a );
 
449
            *ret_mpi = a;
 
450
        }
 
451
        else
 
452
            mpi_free(a);
 
453
        return 0;
 
454
    }
 
455
    else
 
456
        return GCRYERR_INV_ARG;
 
457
}
 
458
 
 
459
/****************
 
460
 * Write A using FORMAT into buffer which has a length of *NBYTES.
 
461
 * Returns the number of bytes actually written in nbytes.
 
462
 * Buffer maybe NULL to query the required length of the buffer
 
463
 */
 
464
int
 
465
gcry_mpi_print( enum gcry_mpi_format format, char *buffer, size_t *nbytes,
 
466
                 struct gcry_mpi *a )
 
467
{
 
468
    unsigned int nbits = mpi_get_nbits(a);
 
469
    size_t len;
 
470
 
 
471
    if( !nbytes )
 
472
        return GCRYERR_INV_ARG;
 
473
 
 
474
    len = *nbytes;
 
475
    *nbytes = 0;
 
476
    if( format == GCRYMPI_FMT_STD ) {
 
477
        char *tmp;
 
478
        int extra = 0;
 
479
        unsigned int n;
 
480
 
 
481
        if( a->sign )
 
482
            return GCRYERR_INTERNAL; /* can't handle it yet */
 
483
 
 
484
        tmp = _gcry_mpi_get_buffer( a, &n, NULL );
 
485
        if( n && (*tmp & 0x80) ) {
 
486
            n++;
 
487
            extra=1;
 
488
        }
 
489
 
 
490
        if( n > len && buffer ) {
 
491
            gcry_free(tmp);
 
492
            return GCRYERR_TOO_SHORT;  /* the provided buffer is too short */
 
493
        }
 
494
        if( buffer ) {
 
495
            byte *s = buffer;
 
496
            if( extra )
 
497
                *s++ = 0;
 
498
 
 
499
            memcpy( s, tmp, n-extra );
 
500
        }
 
501
        gcry_free(tmp);
 
502
        *nbytes = n;
 
503
        return 0;
 
504
    }
 
505
    else if( format == GCRYMPI_FMT_USG ) {
 
506
        unsigned int n = (nbits + 7)/8;
 
507
 
 
508
        /* we ignore the sign for this format */
 
509
        /* FIXME: for performance reasons we should put this into
 
510
         * mpi_aprint becuase we can then use the buffer directly */
 
511
        if( n > len && buffer )
 
512
            return GCRYERR_TOO_SHORT;  /* the provided buffer is too short */
 
513
        if( buffer ) {
 
514
            char *tmp;
 
515
            tmp = _gcry_mpi_get_buffer( a, &n, NULL );
 
516
            memcpy( buffer, tmp, n );
 
517
            gcry_free(tmp);
 
518
        }
 
519
        *nbytes = n;
 
520
        return 0;
 
521
    }
 
522
#if 0
 
523
    else if( format == GCRYMPI_FMT_PGP ) {
 
524
        unsigned int n = (nbits + 7)/8;
 
525
 
 
526
        if( a->sign )
 
527
            return GCRYERR_INV_ARG; /* pgp format can only handle unsigned */
 
528
 
 
529
        if( n+2 > len && buffer )
 
530
            return GCRYERR_TOO_SHORT;  /* the provided buffer is too short */
 
531
        if( buffer ) {
 
532
            char *tmp;
 
533
            byte *s = buffer;
 
534
            s[0] = nbits >> 8;
 
535
            s[1] = nbits;
 
536
 
 
537
            tmp = _gcry_mpi_get_buffer( a, &n, NULL );
 
538
            memcpy( s+2, tmp, n );
 
539
            gcry_free(tmp);
 
540
        }
 
541
        *nbytes = n+2;
 
542
        return 0;
 
543
    }
 
544
    else if( format == GCRYMPI_FMT_SSH ) {
 
545
        char *tmp;
 
546
        int extra = 0;
 
547
        unsigned int n;
 
548
 
 
549
        if( a->sign )
 
550
            return GCRYERR_INTERNAL; /* can't handle it yet */
 
551
 
 
552
        tmp = _gcry_mpi_get_buffer( a, &n, NULL );
 
553
        if( n && (*tmp & 0x80) ) {
 
554
            n++;
 
555
            extra=1;
 
556
        }
 
557
 
 
558
        if( n+4 > len && buffer ) {
 
559
            gcry_free(tmp);
 
560
            return GCRYERR_TOO_SHORT;  /* the provided buffer is too short */
 
561
        }
 
562
        if( buffer ) {
 
563
            byte *s = buffer;
 
564
            *s++ = n >> 24;
 
565
            *s++ = n >> 16;
 
566
            *s++ = n >> 8;
 
567
            *s++ = n;
 
568
            if( extra )
 
569
                *s++ = 0;
 
570
 
 
571
            memcpy( s, tmp, n-extra );
 
572
        }
 
573
        gcry_free(tmp);
 
574
        *nbytes = 4+n;
 
575
        return 0;
 
576
    }
 
577
    else if( format == GCRYMPI_FMT_HEX ) {
 
578
        byte *tmp;
 
579
        int i;
 
580
        int extra = 0;
 
581
        unsigned int n=0;
 
582
 
 
583
        tmp = _gcry_mpi_get_buffer( a, &n, NULL );
 
584
        if( !n || (*tmp & 0x80) )
 
585
            extra=2;
 
586
 
 
587
        if( 2*n + extra + !!a->sign + 1 > len && buffer ) {
 
588
            gcry_free(tmp);
 
589
            return GCRYERR_TOO_SHORT;  /* the provided buffer is too short */
 
590
        }
 
591
        if( buffer ) {
 
592
            byte *s = buffer;
 
593
            if( a->sign )
 
594
                *s++ = '-';
 
595
            if( extra ) {
 
596
                *s++ = '0';
 
597
                *s++ = '0';
 
598
            }
 
599
 
 
600
            for(i=0; i < n; i++ ) {
 
601
                unsigned int c = tmp[i];
 
602
                *s++ = (c >> 4) < 10? '0'+(c>>4) : 'A'+(c>>4)-10 ;
 
603
                c &= 15;
 
604
                *s++ = c < 10? '0'+c : 'A'+c-10 ;
 
605
            }
 
606
            *s++ = 0;
 
607
            *nbytes = (char*)s - buffer;
 
608
        }
 
609
        else {
 
610
            *nbytes = 2*n + extra + !!a->sign + 1;
 
611
        }
 
612
        gcry_free(tmp);
 
613
        return 0;
 
614
    }
 
615
#endif
 
616
    else
 
617
        return GCRYERR_INV_ARG;
 
618
}
 
619
 
 
620
/****************
 
621
 * Like gcry_mpi_print but this function allocates the buffer itself.
 
622
 * The caller has to supply the address of a pointer. nbytes may be
 
623
 * NULL.
 
624
 */
 
625
int
 
626
gcry_mpi_aprint( enum gcry_mpi_format format, void **buffer, size_t *nbytes,
 
627
                 struct gcry_mpi *a )
 
628
{
 
629
    size_t n;
 
630
    int rc;
 
631
 
 
632
    *buffer = NULL;
 
633
    rc = gcry_mpi_print( format, NULL, &n, a );
 
634
    if( rc )
 
635
        return rc;
 
636
    *buffer = mpi_is_secure(a) ? gcry_xmalloc_secure( n ) : gcry_xmalloc( n );
 
637
    rc = gcry_mpi_print( format, *buffer, &n, a );
 
638
    if( rc ) {
 
639
        gcry_free(*buffer);
 
640
        *buffer = NULL;
 
641
    }
 
642
    else if( nbytes )
 
643
        *nbytes = n;
 
644
    return rc;
 
645
}
 
646
 
 
647