/src/libgcrypt/mpi/mpicoder.c
Line | Count | Source (jump to first uncovered line) |
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, 2014 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 | | #include "../cipher/bufhelp.h" |
30 | | |
31 | | /* The maximum length we support in the functions converting an |
32 | | * external representation to an MPI. This limit is used to catch |
33 | | * programming errors and to avoid DoS due to insane long allocations. |
34 | | * The 16 MiB limit is actually ridiculous large but some of those PQC |
35 | | * algorithms use quite large keys and they might end up using MPIs |
36 | | * for that. */ |
37 | 79.8k | #define MAX_EXTERN_SCAN_BYTES (16*1024*1024) |
38 | | |
39 | | /* The maximum length (in bits) we support for OpenPGP MPIs. Note |
40 | | * that OpenPGP's MPI format uses only two bytes and thus would be |
41 | | * limited to 64k anyway. Note that this limit matches that used by |
42 | | * GnuPG. */ |
43 | 79.8k | #define MAX_EXTERN_MPI_BITS 16384 |
44 | | |
45 | | |
46 | | /* Helper used to scan PGP style MPIs. Returns NULL on failure. */ |
47 | | static gcry_mpi_t |
48 | | mpi_read_from_buffer (const unsigned char *buffer, unsigned *ret_nread, |
49 | | int secure) |
50 | 79.8k | { |
51 | 79.8k | int i, j; |
52 | 79.8k | unsigned int nbits, nbytes, nlimbs, nread=0; |
53 | 79.8k | mpi_limb_t a; |
54 | 79.8k | gcry_mpi_t val = MPI_NULL; |
55 | 79.8k | unsigned int max_nread = *ret_nread; |
56 | | |
57 | 79.8k | if ( max_nread < 2 ) |
58 | 0 | goto leave; |
59 | 79.8k | nbits = buffer[0] << 8 | buffer[1]; |
60 | 79.8k | if ( nbits > MAX_EXTERN_MPI_BITS ) |
61 | 0 | { |
62 | | /* log_debug ("mpi too large (%u bits)\n", nbits); */ |
63 | 0 | goto leave; |
64 | 0 | } |
65 | 79.8k | buffer += 2; |
66 | 79.8k | nread = 2; |
67 | | |
68 | 79.8k | nbytes = (nbits+7) / 8; |
69 | 79.8k | nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; |
70 | 79.8k | val = secure? mpi_alloc_secure (nlimbs) : mpi_alloc (nlimbs); |
71 | 79.8k | i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; |
72 | 79.8k | i %= BYTES_PER_MPI_LIMB; |
73 | 79.8k | j= val->nlimbs = nlimbs; |
74 | 79.8k | val->sign = 0; |
75 | 105k | for ( ; j > 0; j-- ) |
76 | 26.0k | { |
77 | 26.0k | a = 0; |
78 | 26.0k | if (i == 0 && nread + BYTES_PER_MPI_LIMB <= max_nread) |
79 | 18.1k | { |
80 | | #if BYTES_PER_MPI_LIMB == 4 |
81 | | a = buf_get_be32 (buffer); |
82 | | #elif BYTES_PER_MPI_LIMB == 8 |
83 | 18.1k | a = buf_get_be64 (buffer); |
84 | | #else |
85 | | # error please implement for this limb size. |
86 | | #endif |
87 | 18.1k | buffer += BYTES_PER_MPI_LIMB; |
88 | 18.1k | nread += BYTES_PER_MPI_LIMB; |
89 | 18.1k | i += BYTES_PER_MPI_LIMB; |
90 | 18.1k | } |
91 | 43.3k | for (; i < BYTES_PER_MPI_LIMB; i++ ) |
92 | 17.3k | { |
93 | 17.3k | if ( ++nread > max_nread ) |
94 | 0 | { |
95 | | /* log_debug ("mpi larger than buffer"); */ |
96 | 0 | mpi_free (val); |
97 | 0 | val = NULL; |
98 | 0 | goto leave; |
99 | 0 | } |
100 | 17.3k | a <<= 8; |
101 | 17.3k | a |= *buffer++; |
102 | 17.3k | } |
103 | 26.0k | i = 0; |
104 | 26.0k | val->d[j-1] = a; |
105 | 26.0k | } |
106 | | |
107 | 79.8k | leave: |
108 | 79.8k | *ret_nread = nread; |
109 | 79.8k | return val; |
110 | 79.8k | } |
111 | | |
112 | | |
113 | | /**************** |
114 | | * Fill the mpi VAL from the hex string in STR. |
115 | | */ |
116 | | static int |
117 | | mpi_fromstr (gcry_mpi_t val, const char *str, size_t slen) |
118 | 0 | { |
119 | 0 | static const int hex2int[2][256] = |
120 | 0 | { |
121 | 0 | { |
122 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
123 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
124 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x00, 0x10, 0x20, 0x30, |
125 | 0 | 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, -1, -1, -1, -1, -1, -1, -1, 0xa0, |
126 | 0 | 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
127 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0xa0, |
128 | 0 | 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
129 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
130 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
131 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
132 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
133 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
134 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
135 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
136 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 |
137 | 0 | }, |
138 | 0 | { |
139 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
140 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
141 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x00, 0x01, 0x02, 0x03, |
142 | 0 | 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, -1, -1, -1, -1, -1, -1, -1, 0x0a, |
143 | 0 | 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
144 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x0a, |
145 | 0 | 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
146 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
147 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
148 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
149 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
150 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
151 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
152 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
153 | 0 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 |
154 | 0 | } |
155 | 0 | }; |
156 | 0 | int sign = 0; |
157 | 0 | int prepend_zero = 0; |
158 | 0 | int i, j, c, c1, c2; |
159 | 0 | unsigned int nbits, nbytes, nlimbs; |
160 | 0 | mpi_limb_t a; |
161 | |
|
162 | 0 | if ( *str == '-' ) |
163 | 0 | { |
164 | 0 | sign = 1; |
165 | 0 | str++; |
166 | 0 | slen--; |
167 | 0 | } |
168 | | |
169 | | /* Skip optional hex prefix. */ |
170 | 0 | if ( *str == '0' && str[1] == 'x' ) |
171 | 0 | { |
172 | 0 | str += 2; |
173 | 0 | slen -= 2; |
174 | 0 | } |
175 | |
|
176 | 0 | nbits = slen * 4; |
177 | 0 | if ((nbits % 8)) |
178 | 0 | prepend_zero = 1; |
179 | |
|
180 | 0 | nbytes = (nbits+7) / 8; |
181 | 0 | nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; |
182 | |
|
183 | 0 | if ( val->alloced < nlimbs ) |
184 | 0 | mpi_resize (val, nlimbs); |
185 | |
|
186 | 0 | i = BYTES_PER_MPI_LIMB - (nbytes % BYTES_PER_MPI_LIMB); |
187 | 0 | i %= BYTES_PER_MPI_LIMB; |
188 | 0 | j = val->nlimbs = nlimbs; |
189 | 0 | val->sign = sign; |
190 | 0 | for (; j > 0; j--) |
191 | 0 | { |
192 | 0 | a = 0; |
193 | |
|
194 | 0 | if (prepend_zero == 0 && (i & 31) == 0) |
195 | 0 | { |
196 | 0 | while (slen >= sizeof(u32) * 2) |
197 | 0 | { |
198 | 0 | u32 n, m; |
199 | 0 | u32 x, y; |
200 | |
|
201 | 0 | x = buf_get_le32(str); |
202 | 0 | y = buf_get_le32(str + 4); |
203 | 0 | str += 8; |
204 | 0 | slen -= 8; |
205 | |
|
206 | 0 | a <<= 31; /* Two step to avoid compiler warning on 32-bit. */ |
207 | 0 | a <<= 1; |
208 | |
|
209 | 0 | n = (hex2int[0][(x >> 0) & 0xff] |
210 | 0 | | hex2int[1][(x >> 8) & 0xff]) << 8; |
211 | 0 | m = (hex2int[0][(y >> 0) & 0xff] |
212 | 0 | | hex2int[1][(y >> 8) & 0xff]) << 8; |
213 | 0 | n |= hex2int[0][(x >> 16) & 0xff]; |
214 | 0 | n |= hex2int[1][(x >> 24) & 0xff]; |
215 | 0 | m |= hex2int[0][(y >> 16) & 0xff]; |
216 | 0 | m |= hex2int[1][(y >> 24) & 0xff]; |
217 | |
|
218 | 0 | a |= (n << 16) | m; |
219 | 0 | i += 32; |
220 | 0 | if ((int)(n | m) < 0) |
221 | 0 | { |
222 | | /* Invalid character. */ |
223 | 0 | mpi_clear (val); |
224 | 0 | return 1; /* Error. */ |
225 | 0 | } |
226 | 0 | if (i == BITS_PER_MPI_LIMB) |
227 | 0 | break; |
228 | 0 | } |
229 | 0 | } |
230 | | |
231 | 0 | for (; i < BYTES_PER_MPI_LIMB; i++) |
232 | 0 | { |
233 | 0 | if (prepend_zero) |
234 | 0 | { |
235 | 0 | c1 = '0'; |
236 | 0 | prepend_zero = 0; |
237 | 0 | } |
238 | 0 | else |
239 | 0 | { |
240 | 0 | c1 = *str++; |
241 | 0 | slen--; |
242 | 0 | } |
243 | |
|
244 | 0 | if (!c1) |
245 | 0 | { |
246 | 0 | mpi_clear (val); |
247 | 0 | return 1; /* Error. */ |
248 | 0 | } |
249 | 0 | c2 = *str++; |
250 | 0 | slen--; |
251 | 0 | if (!c2) |
252 | 0 | { |
253 | 0 | mpi_clear (val); |
254 | 0 | return 1; /* Error. */ |
255 | 0 | } |
256 | 0 | c = hex2int[0][c1 & 0xff]; |
257 | 0 | c |= hex2int[1][c2 & 0xff]; |
258 | 0 | if (c < 0) |
259 | 0 | { |
260 | 0 | mpi_clear(val); |
261 | 0 | return 1; /* Error. */ |
262 | 0 | } |
263 | 0 | a <<= 8; |
264 | 0 | a |= c; |
265 | 0 | } |
266 | 0 | i = 0; |
267 | 0 | val->d[j-1] = a; |
268 | 0 | } |
269 | | |
270 | 0 | return 0; /* Okay. */ |
271 | 0 | } |
272 | | |
273 | | |
274 | | /* Return an allocated buffer with the MPI (msb first). NBYTES |
275 | | receives the length of this buffer. If FILL_LE is not 0, the |
276 | | returned value is stored as little endian and right padded with |
277 | | zeroes so that the returned buffer has at least FILL_LE bytes. |
278 | | |
279 | | If EXTRAALLOC > 0 the returned buffer has these number of bytes |
280 | | extra allocated at the end; if EXTRAALLOC < 0 the returned buffer |
281 | | has the absolute value of EXTRAALLOC allocated at the begin of the |
282 | | buffer (the are not initialized) and the MPI is stored right after |
283 | | this. This feature is useful to allow the caller to prefix the |
284 | | returned value. EXTRAALLOC is _not_ included in the value stored |
285 | | at NBYTES. |
286 | | |
287 | | Caller must free the return string. This function returns an |
288 | | allocated buffer with NBYTES set to zero if the value of A is zero. |
289 | | If sign is not NULL, it will be set to the sign of the A. On error |
290 | | NULL is returned and ERRNO set appropriately. */ |
291 | | static unsigned char * |
292 | | do_get_buffer (gcry_mpi_t a, unsigned int fill_le, int extraalloc, |
293 | | unsigned int *nbytes, int *sign, int force_secure) |
294 | 68.1k | { |
295 | 68.1k | unsigned char *p, *buffer, *retbuffer; |
296 | 68.1k | unsigned int length, tmp; |
297 | 68.1k | mpi_limb_t alimb; |
298 | 68.1k | int i; |
299 | 68.1k | size_t n, n2; |
300 | | |
301 | 68.1k | if (sign) |
302 | 0 | *sign = a->sign; |
303 | | |
304 | 68.1k | *nbytes = a->nlimbs * BYTES_PER_MPI_LIMB; |
305 | 68.1k | n = *nbytes? *nbytes:1; /* Allocate at least one byte. */ |
306 | 68.1k | if (n < fill_le) |
307 | 0 | n = fill_le; |
308 | 68.1k | if (extraalloc < 0) |
309 | 0 | n2 = n + -extraalloc; |
310 | 68.1k | else |
311 | 68.1k | n2 = n + extraalloc; |
312 | | |
313 | 68.1k | retbuffer = (force_secure || mpi_is_secure(a))? xtrymalloc_secure (n2) |
314 | 68.1k | : xtrymalloc (n2); |
315 | 68.1k | if (!retbuffer) |
316 | 0 | return NULL; |
317 | 68.1k | if (extraalloc < 0) |
318 | 0 | buffer = retbuffer + -extraalloc; |
319 | 68.1k | else |
320 | 68.1k | buffer = retbuffer; |
321 | 68.1k | p = buffer; |
322 | | |
323 | 87.0k | for (i=a->nlimbs-1; i >= 0; i--) |
324 | 18.8k | { |
325 | 18.8k | alimb = a->d[i]; |
326 | | #if BYTES_PER_MPI_LIMB == 4 |
327 | | buf_put_be32 (p, alimb); |
328 | | p += 4; |
329 | | #elif BYTES_PER_MPI_LIMB == 8 |
330 | 18.8k | buf_put_be64 (p, alimb); |
331 | 18.8k | p += 8; |
332 | | #else |
333 | | # error please implement for this limb size. |
334 | | #endif |
335 | 18.8k | } |
336 | | |
337 | 68.1k | if (fill_le) |
338 | 0 | { |
339 | 0 | length = *nbytes; |
340 | | /* Reverse buffer and pad with zeroes. */ |
341 | 0 | for (i = 0; i + 8 < length / 2; i += 8) |
342 | 0 | { |
343 | 0 | u64 head = buf_get_be64 (buffer + i); |
344 | 0 | u64 tail = buf_get_be64 (buffer + length - 8 - i); |
345 | 0 | buf_put_le64 (buffer + length - 8 - i, head); |
346 | 0 | buf_put_le64 (buffer + i, tail); |
347 | 0 | } |
348 | 0 | if (i + 4 < length / 2) |
349 | 0 | { |
350 | 0 | u32 head = buf_get_be32 (buffer + i); |
351 | 0 | u32 tail = buf_get_be32 (buffer + length - 4 - i); |
352 | 0 | buf_put_le32 (buffer + length - 4 - i, head); |
353 | 0 | buf_put_le32 (buffer + i, tail); |
354 | 0 | i += 4; |
355 | 0 | } |
356 | 0 | for (; i < length/2; i++) |
357 | 0 | { |
358 | 0 | tmp = buffer[i]; |
359 | 0 | buffer[i] = buffer[length-1-i]; |
360 | 0 | buffer[length-1-i] = tmp; |
361 | 0 | } |
362 | | /* Pad with zeroes. */ |
363 | 0 | for (p = buffer + length; length < fill_le; length++) |
364 | 0 | *p++ = 0; |
365 | 0 | *nbytes = length; |
366 | |
|
367 | 0 | return retbuffer; |
368 | 0 | } |
369 | | |
370 | | /* This is sub-optimal but we need to do the shift operation because |
371 | | the caller has to free the returned buffer. */ |
372 | 93.3k | for (p=buffer; *nbytes && !*p; p++, --*nbytes) |
373 | 25.1k | ; |
374 | 68.1k | if (p != buffer) |
375 | 4.50k | memmove (buffer, p, *nbytes); |
376 | 68.1k | return retbuffer; |
377 | 68.1k | } |
378 | | |
379 | | |
380 | | byte * |
381 | | _gcry_mpi_get_buffer (gcry_mpi_t a, unsigned int fill_le, |
382 | | unsigned int *r_nbytes, int *sign) |
383 | 68.1k | { |
384 | 68.1k | if (mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)) |
385 | 0 | { |
386 | 0 | unsigned int nbits; |
387 | 0 | byte *p = _gcry_mpi_get_opaque_copy (a, &nbits); |
388 | |
|
389 | 0 | if (r_nbytes) |
390 | 0 | *r_nbytes = (nbits+7)/8; |
391 | |
|
392 | 0 | return p; |
393 | 0 | } |
394 | 68.1k | else |
395 | 68.1k | return do_get_buffer (a, fill_le, 0, r_nbytes, sign, 0); |
396 | 68.1k | } |
397 | | |
398 | | byte * |
399 | | _gcry_mpi_get_buffer_extra (gcry_mpi_t a, unsigned int fill_le, int extraalloc, |
400 | | unsigned int *r_nbytes, int *sign) |
401 | 0 | { |
402 | 0 | return do_get_buffer (a, fill_le, extraalloc, r_nbytes, sign, 0); |
403 | 0 | } |
404 | | |
405 | | byte * |
406 | | _gcry_mpi_get_secure_buffer (gcry_mpi_t a, unsigned int fill_le, |
407 | | unsigned int *r_nbytes, int *sign) |
408 | 0 | { |
409 | 0 | return do_get_buffer (a, fill_le, 0, r_nbytes, sign, 1); |
410 | 0 | } |
411 | | |
412 | | |
413 | | /* |
414 | | * Use the NBYTES at BUFFER_ARG to update A. Set the sign of a to |
415 | | * SIGN. |
416 | | */ |
417 | | void |
418 | | _gcry_mpi_set_buffer (gcry_mpi_t a, const void *buffer_arg, |
419 | | unsigned int nbytes, int sign) |
420 | 0 | { |
421 | 0 | const unsigned char *buffer = (const unsigned char*)buffer_arg; |
422 | 0 | const unsigned char *p; |
423 | 0 | mpi_limb_t alimb; |
424 | 0 | int nlimbs; |
425 | 0 | int i; |
426 | |
|
427 | 0 | if (mpi_is_immutable (a)) |
428 | 0 | { |
429 | 0 | mpi_immutable_failed (); |
430 | 0 | return; |
431 | 0 | } |
432 | | |
433 | 0 | nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB; |
434 | 0 | RESIZE_IF_NEEDED(a, nlimbs); |
435 | 0 | a->sign = sign; |
436 | |
|
437 | 0 | for (i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; ) |
438 | 0 | { |
439 | | #if BYTES_PER_MPI_LIMB == 4 |
440 | | alimb = buf_get_be32(p - 4 + 1); |
441 | | p -= 4; |
442 | | #elif BYTES_PER_MPI_LIMB == 8 |
443 | 0 | alimb = buf_get_be64(p - 8 + 1); |
444 | 0 | p -= 8; |
445 | | #else |
446 | | # error please implement for this limb size. |
447 | | #endif |
448 | 0 | a->d[i++] = alimb; |
449 | 0 | } |
450 | 0 | if ( p >= buffer ) |
451 | 0 | { |
452 | 0 | byte last[BYTES_PER_MPI_LIMB] = { 0 }; |
453 | 0 | unsigned int n = (p - buffer) + 1; |
454 | |
|
455 | 0 | n = n > BYTES_PER_MPI_LIMB ? BYTES_PER_MPI_LIMB : n; |
456 | 0 | memcpy (last + BYTES_PER_MPI_LIMB - n, p - n + 1, n); |
457 | 0 | p -= n; |
458 | |
|
459 | | #if BYTES_PER_MPI_LIMB == 4 |
460 | | alimb = buf_get_be32(last); |
461 | | #elif BYTES_PER_MPI_LIMB == 8 |
462 | 0 | alimb = buf_get_be64(last); |
463 | | #else |
464 | | # error please implement for this limb size. |
465 | | #endif |
466 | |
|
467 | 0 | a->d[i++] = alimb; |
468 | 0 | } |
469 | 0 | a->nlimbs = i; |
470 | 0 | gcry_assert (i == nlimbs); |
471 | 0 | } |
472 | | |
473 | | |
474 | | static void |
475 | | onecompl (gcry_mpi_t a) |
476 | 0 | { |
477 | 0 | mpi_ptr_t ap; |
478 | 0 | mpi_size_t n; |
479 | 0 | unsigned int i; |
480 | 0 | unsigned int nbits; |
481 | |
|
482 | 0 | if (!a || mpi_is_immutable (a)) |
483 | 0 | { |
484 | 0 | mpi_immutable_failed (); |
485 | 0 | return; |
486 | 0 | } |
487 | | |
488 | 0 | nbits = mpi_get_nbits (a); |
489 | |
|
490 | 0 | mpi_normalize (a); |
491 | 0 | ap = a->d; |
492 | 0 | n = a->nlimbs; |
493 | |
|
494 | 0 | for( i = 0; i < n; i++ ) |
495 | 0 | ap[i] ^= (mpi_limb_t)(-1); |
496 | |
|
497 | 0 | a->sign = 0; |
498 | 0 | mpi_clear_highbit (a, nbits-1); |
499 | 0 | } |
500 | | |
501 | | |
502 | | /* Perform a two's complement operation on buffer P of size N bytes. */ |
503 | | static void |
504 | | twocompl (unsigned char *p, unsigned int n) |
505 | 0 | { |
506 | 0 | int i; |
507 | |
|
508 | 0 | for (i=n-1; i >= 0 && !p[i]; i--) |
509 | 0 | ; |
510 | 0 | if (i >= 0) |
511 | 0 | { |
512 | 0 | unsigned char pi = p[i]; |
513 | 0 | unsigned int ntz = _gcry_ctz (pi); |
514 | |
|
515 | 0 | p[i] = ((p[i] ^ (0xfe << ntz)) | (0x01 << ntz)) & (0xff << ntz); |
516 | |
|
517 | 0 | for (i--; i >= 7; i -= 8) |
518 | 0 | { |
519 | 0 | buf_put_he64(&p[i-7], ~buf_get_he64(&p[i-7])); |
520 | 0 | } |
521 | 0 | if (i >= 3) |
522 | 0 | { |
523 | 0 | buf_put_he32(&p[i-3], ~buf_get_he32(&p[i-3])); |
524 | 0 | i -= 4; |
525 | 0 | } |
526 | 0 | for (; i >= 0; i--) |
527 | 0 | { |
528 | 0 | p[i] ^= 0xff; |
529 | 0 | } |
530 | 0 | } |
531 | 0 | } |
532 | | |
533 | | |
534 | | /* Convert the external representation of an integer stored in BUFFER |
535 | | * with a length of BUFLEN into a newly create MPI returned in |
536 | | * RET_MPI. If NSCANNED is not NULL, it will receive the number of |
537 | | * bytes actually scanned after a successful operation. */ |
538 | | gcry_err_code_t |
539 | | _gcry_mpi_scan (struct gcry_mpi **ret_mpi, enum gcry_mpi_format format, |
540 | | const void *buffer_arg, size_t buflen, size_t *nscanned) |
541 | 79.8k | { |
542 | 79.8k | const unsigned char *buffer = (const unsigned char*)buffer_arg; |
543 | 79.8k | struct gcry_mpi *a = NULL; |
544 | 79.8k | unsigned int len; |
545 | 79.8k | int secure = (buffer && _gcry_is_secure (buffer)); |
546 | | |
547 | 79.8k | if (buflen > MAX_EXTERN_SCAN_BYTES) |
548 | 0 | { |
549 | 0 | if (nscanned) |
550 | 0 | *nscanned = 0; |
551 | 0 | return GPG_ERR_INV_OBJ; |
552 | 0 | } |
553 | | |
554 | 79.8k | if (format == GCRYMPI_FMT_SSH) |
555 | 0 | len = 0; |
556 | 79.8k | else |
557 | 79.8k | len = buflen; |
558 | | |
559 | 79.8k | if (format == GCRYMPI_FMT_STD) |
560 | 0 | { |
561 | 0 | const unsigned char *s = buffer; |
562 | |
|
563 | 0 | a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1) |
564 | 0 | /BYTES_PER_MPI_LIMB) |
565 | 0 | : mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB); |
566 | 0 | if (len) |
567 | 0 | { |
568 | 0 | _gcry_mpi_set_buffer (a, s, len, 0); |
569 | 0 | a->sign = !!(*s & 0x80); |
570 | 0 | if (a->sign) |
571 | 0 | { |
572 | 0 | onecompl (a); |
573 | 0 | mpi_add_ui (a, a, 1); |
574 | 0 | a->sign = 1; |
575 | 0 | } |
576 | 0 | } |
577 | 0 | if (ret_mpi) |
578 | 0 | { |
579 | 0 | mpi_normalize ( a ); |
580 | 0 | *ret_mpi = a; |
581 | 0 | } |
582 | 0 | else |
583 | 0 | mpi_free(a); |
584 | 0 | if (nscanned) |
585 | 0 | *nscanned = len; |
586 | 0 | return 0; |
587 | 0 | } |
588 | 79.8k | else if (format == GCRYMPI_FMT_USG) |
589 | 0 | { |
590 | 0 | a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1) |
591 | 0 | /BYTES_PER_MPI_LIMB) |
592 | 0 | : mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB); |
593 | |
|
594 | 0 | if (len) |
595 | 0 | _gcry_mpi_set_buffer (a, buffer, len, 0); |
596 | 0 | if (ret_mpi) |
597 | 0 | { |
598 | 0 | mpi_normalize ( a ); |
599 | 0 | *ret_mpi = a; |
600 | 0 | } |
601 | 0 | else |
602 | 0 | mpi_free(a); |
603 | 0 | if (nscanned) |
604 | 0 | *nscanned = len; |
605 | 0 | return 0; |
606 | 0 | } |
607 | 79.8k | else if (format == GCRYMPI_FMT_PGP) |
608 | 79.8k | { |
609 | 79.8k | a = mpi_read_from_buffer (buffer, &len, secure); |
610 | 79.8k | if (nscanned) |
611 | 79.8k | *nscanned = len; |
612 | 79.8k | if (ret_mpi && a) |
613 | 79.8k | { |
614 | 79.8k | mpi_normalize (a); |
615 | 79.8k | *ret_mpi = a; |
616 | 79.8k | } |
617 | 0 | else if (a) |
618 | 0 | { |
619 | 0 | mpi_free(a); |
620 | 0 | a = NULL; |
621 | 0 | } |
622 | 79.8k | return a? 0 : GPG_ERR_INV_OBJ; |
623 | 79.8k | } |
624 | 0 | else if (format == GCRYMPI_FMT_SSH) |
625 | 0 | { |
626 | 0 | const unsigned char *s = buffer; |
627 | 0 | size_t n; |
628 | | |
629 | | /* This test is not strictly necessary and an assert (!len) |
630 | | would be sufficient. We keep this test in case we later |
631 | | allow the BUFLEN argument to act as a sanitiy check. Same |
632 | | below. */ |
633 | 0 | if (len && len < 4) |
634 | 0 | return GPG_ERR_TOO_SHORT; |
635 | | |
636 | 0 | n = buf_get_be32 (s); |
637 | 0 | s += 4; |
638 | 0 | if (len) |
639 | 0 | len -= 4; |
640 | 0 | if (len && n > len) |
641 | 0 | return GPG_ERR_TOO_LARGE; |
642 | | |
643 | 0 | a = secure? mpi_alloc_secure ((n+BYTES_PER_MPI_LIMB-1) |
644 | 0 | /BYTES_PER_MPI_LIMB) |
645 | 0 | : mpi_alloc ((n+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB); |
646 | 0 | if (n) |
647 | 0 | { |
648 | 0 | _gcry_mpi_set_buffer( a, s, n, 0 ); |
649 | 0 | a->sign = !!(*s & 0x80); |
650 | 0 | if (a->sign) |
651 | 0 | { |
652 | 0 | onecompl (a); |
653 | 0 | mpi_add_ui (a, a, 1); |
654 | 0 | a->sign = 1; |
655 | 0 | } |
656 | 0 | } |
657 | 0 | if (nscanned) |
658 | 0 | *nscanned = n+4; |
659 | 0 | if (ret_mpi) |
660 | 0 | { |
661 | 0 | mpi_normalize ( a ); |
662 | 0 | *ret_mpi = a; |
663 | 0 | } |
664 | 0 | else |
665 | 0 | mpi_free(a); |
666 | 0 | return 0; |
667 | 0 | } |
668 | 0 | else if (format == GCRYMPI_FMT_HEX) |
669 | 0 | { |
670 | 0 | size_t slen; |
671 | | /* We can only handle C strings for now. */ |
672 | 0 | if (buflen) |
673 | 0 | return GPG_ERR_INV_ARG; |
674 | | |
675 | 0 | slen = strlen ((const char *)buffer); |
676 | 0 | if (slen > MAX_EXTERN_SCAN_BYTES) |
677 | 0 | return GPG_ERR_INV_OBJ; |
678 | 0 | a = secure? mpi_alloc_secure ((((slen+1)/2)+BYTES_PER_MPI_LIMB-1) |
679 | 0 | /BYTES_PER_MPI_LIMB) |
680 | 0 | : mpi_alloc((((slen+1)/2)+BYTES_PER_MPI_LIMB-1) |
681 | 0 | /BYTES_PER_MPI_LIMB); |
682 | 0 | if (mpi_fromstr (a, (const char *)buffer, slen)) |
683 | 0 | { |
684 | 0 | mpi_free (a); |
685 | 0 | return GPG_ERR_INV_OBJ; |
686 | 0 | } |
687 | 0 | if (ret_mpi) |
688 | 0 | { |
689 | 0 | mpi_normalize ( a ); |
690 | 0 | *ret_mpi = a; |
691 | 0 | } |
692 | 0 | else |
693 | 0 | mpi_free(a); |
694 | 0 | if (nscanned) |
695 | 0 | *nscanned = strlen ((const char*)buffer); |
696 | 0 | return 0; |
697 | 0 | } |
698 | 0 | else |
699 | 0 | return GPG_ERR_INV_ARG; |
700 | 79.8k | } |
701 | | |
702 | | |
703 | | /* Convert the big integer A into the external representation |
704 | | described by FORMAT and store it in the provided BUFFER which has |
705 | | been allocated by the user with a size of BUFLEN bytes. NWRITTEN |
706 | | receives the actual length of the external representation unless it |
707 | | has been passed as NULL. BUFFER may be NULL to query the required |
708 | | length. */ |
709 | | gcry_err_code_t |
710 | | _gcry_mpi_print (enum gcry_mpi_format format, |
711 | | unsigned char *buffer, size_t buflen, |
712 | | size_t *nwritten, struct gcry_mpi *a) |
713 | 136k | { |
714 | 136k | unsigned int nbits = mpi_get_nbits (a); |
715 | 136k | size_t len; |
716 | 136k | size_t dummy_nwritten; |
717 | 136k | int negative; |
718 | | |
719 | 136k | if (!nwritten) |
720 | 0 | nwritten = &dummy_nwritten; |
721 | | |
722 | | /* Libgcrypt does no always care to set clear the sign if the value |
723 | | is 0. For printing this is a bit of a surprise, in particular |
724 | | because if some of the formats don't support negative numbers but |
725 | | should be able to print a zero. Thus we need this extra test |
726 | | for a negative number. */ |
727 | 136k | if (a->sign && _gcry_mpi_cmp_ui (a, 0)) |
728 | 0 | negative = 1; |
729 | 136k | else |
730 | 136k | negative = 0; |
731 | | |
732 | 136k | len = buflen; |
733 | 136k | *nwritten = 0; |
734 | 136k | if (format == GCRYMPI_FMT_STD) |
735 | 0 | { |
736 | 0 | unsigned char *tmp; |
737 | 0 | int extra = 0; |
738 | 0 | unsigned int n; |
739 | |
|
740 | 0 | tmp = _gcry_mpi_get_buffer (a, 0, &n, NULL); |
741 | 0 | if (!tmp) |
742 | 0 | return gpg_err_code_from_syserror (); |
743 | | |
744 | 0 | if (negative) |
745 | 0 | { |
746 | 0 | twocompl (tmp, n); |
747 | 0 | if (!(*tmp & 0x80)) |
748 | 0 | { |
749 | | /* Need to extend the sign. */ |
750 | 0 | n++; |
751 | 0 | extra = 2; |
752 | 0 | } |
753 | 0 | } |
754 | 0 | else if (n && (*tmp & 0x80)) |
755 | 0 | { |
756 | | /* Positive but the high bit of the returned buffer is set. |
757 | | Thus we need to print an extra leading 0x00 so that the |
758 | | output is interpreted as a positive number. */ |
759 | 0 | n++; |
760 | 0 | extra = 1; |
761 | 0 | } |
762 | |
|
763 | 0 | if (buffer && n > len) |
764 | 0 | { |
765 | | /* The provided buffer is too short. */ |
766 | 0 | xfree (tmp); |
767 | 0 | return GPG_ERR_TOO_SHORT; |
768 | 0 | } |
769 | 0 | if (buffer) |
770 | 0 | { |
771 | 0 | unsigned char *s = buffer; |
772 | |
|
773 | 0 | if (extra == 1) |
774 | 0 | *s++ = 0; |
775 | 0 | else if (extra) |
776 | 0 | *s++ = 0xff; |
777 | 0 | memcpy (s, tmp, n-!!extra); |
778 | 0 | } |
779 | 0 | xfree (tmp); |
780 | 0 | *nwritten = n; |
781 | 0 | return 0; |
782 | 0 | } |
783 | 136k | else if (format == GCRYMPI_FMT_USG) |
784 | 0 | { |
785 | 0 | unsigned int n = (nbits + 7)/8; |
786 | | |
787 | | /* Note: We ignore the sign for this format. */ |
788 | | /* FIXME: for performance reasons we should put this into |
789 | | mpi_aprint because we can then use the buffer directly. */ |
790 | |
|
791 | 0 | if (buffer && n > len) |
792 | 0 | return GPG_ERR_TOO_SHORT; |
793 | 0 | if (buffer) |
794 | 0 | { |
795 | 0 | unsigned char *tmp; |
796 | |
|
797 | 0 | tmp = _gcry_mpi_get_buffer (a, 0, &n, NULL); |
798 | 0 | if (!tmp) |
799 | 0 | return gpg_err_code_from_syserror (); |
800 | 0 | memcpy (buffer, tmp, n); |
801 | 0 | xfree (tmp); |
802 | 0 | } |
803 | 0 | *nwritten = n; |
804 | 0 | return 0; |
805 | 0 | } |
806 | 136k | else if (format == GCRYMPI_FMT_PGP) |
807 | 136k | { |
808 | 136k | unsigned int n = (nbits + 7)/8; |
809 | | |
810 | | /* The PGP format can only handle unsigned integers. */ |
811 | 136k | if (negative) |
812 | 0 | return GPG_ERR_INV_ARG; |
813 | | |
814 | 136k | if (buffer && n+2 > len) |
815 | 0 | return GPG_ERR_TOO_SHORT; |
816 | | |
817 | 136k | if (buffer) |
818 | 68.1k | { |
819 | 68.1k | unsigned char *tmp; |
820 | 68.1k | unsigned char *s = buffer; |
821 | | |
822 | 68.1k | s[0] = nbits >> 8; |
823 | 68.1k | s[1] = nbits; |
824 | | |
825 | 68.1k | tmp = _gcry_mpi_get_buffer (a, 0, &n, NULL); |
826 | 68.1k | if (!tmp) |
827 | 0 | return gpg_err_code_from_syserror (); |
828 | 68.1k | memcpy (s+2, tmp, n); |
829 | 68.1k | xfree (tmp); |
830 | 68.1k | } |
831 | 136k | *nwritten = n+2; |
832 | 136k | return 0; |
833 | 136k | } |
834 | 0 | else if (format == GCRYMPI_FMT_SSH) |
835 | 0 | { |
836 | 0 | unsigned char *tmp; |
837 | 0 | int extra = 0; |
838 | 0 | unsigned int n; |
839 | |
|
840 | 0 | tmp = _gcry_mpi_get_buffer (a, 0, &n, NULL); |
841 | 0 | if (!tmp) |
842 | 0 | return gpg_err_code_from_syserror (); |
843 | | |
844 | 0 | if (negative) |
845 | 0 | { |
846 | 0 | twocompl (tmp, n); |
847 | 0 | if (!(*tmp & 0x80)) |
848 | 0 | { |
849 | | /* Need to extend the sign. */ |
850 | 0 | n++; |
851 | 0 | extra = 2; |
852 | 0 | } |
853 | 0 | } |
854 | 0 | else if (n && (*tmp & 0x80)) |
855 | 0 | { |
856 | 0 | n++; |
857 | 0 | extra=1; |
858 | 0 | } |
859 | |
|
860 | 0 | if (buffer && n+4 > len) |
861 | 0 | { |
862 | 0 | xfree(tmp); |
863 | 0 | return GPG_ERR_TOO_SHORT; |
864 | 0 | } |
865 | | |
866 | 0 | if (buffer) |
867 | 0 | { |
868 | 0 | unsigned char *s = buffer; |
869 | |
|
870 | 0 | buf_put_be32 (s, n); |
871 | 0 | s += 4; |
872 | 0 | if (extra == 1) |
873 | 0 | *s++ = 0; |
874 | 0 | else if (extra) |
875 | 0 | *s++ = 0xff; |
876 | 0 | memcpy (s, tmp, n-!!extra); |
877 | 0 | } |
878 | 0 | xfree (tmp); |
879 | 0 | *nwritten = 4+n; |
880 | 0 | return 0; |
881 | 0 | } |
882 | 0 | else if (format == GCRYMPI_FMT_HEX) |
883 | 0 | { |
884 | 0 | unsigned char *tmp; |
885 | 0 | int i; |
886 | 0 | int extra = 0; |
887 | 0 | unsigned int n = 0; |
888 | |
|
889 | 0 | tmp = _gcry_mpi_get_buffer (a, 0, &n, NULL); |
890 | 0 | if (!tmp) |
891 | 0 | return gpg_err_code_from_syserror (); |
892 | 0 | if (!n || (*tmp & 0x80)) |
893 | 0 | extra = 2; |
894 | |
|
895 | 0 | if (buffer && 2*n + extra + negative + 1 > len) |
896 | 0 | { |
897 | 0 | xfree(tmp); |
898 | 0 | return GPG_ERR_TOO_SHORT; |
899 | 0 | } |
900 | 0 | if (buffer) |
901 | 0 | { |
902 | 0 | static const u32 nibble2hex[] = |
903 | 0 | { |
904 | 0 | '0', '1', '2', '3', '4', '5', '6', '7', |
905 | 0 | '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' |
906 | 0 | }; |
907 | 0 | unsigned char *s = buffer; |
908 | |
|
909 | 0 | if (negative) |
910 | 0 | *s++ = '-'; |
911 | 0 | if (extra) |
912 | 0 | { |
913 | 0 | *s++ = '0'; |
914 | 0 | *s++ = '0'; |
915 | 0 | } |
916 | |
|
917 | 0 | for (i = 0; i + 4 < n; i += 4) |
918 | 0 | { |
919 | 0 | u32 c = buf_get_be32(tmp + i); |
920 | 0 | u32 o1, o2; |
921 | |
|
922 | 0 | o1 = nibble2hex[(c >> 28) & 0xF]; |
923 | 0 | o1 <<= 8; |
924 | 0 | o1 |= nibble2hex[(c >> 24) & 0xF]; |
925 | 0 | o1 <<= 8; |
926 | 0 | o1 |= nibble2hex[(c >> 20) & 0xF]; |
927 | 0 | o1 <<= 8; |
928 | 0 | o1 |= nibble2hex[(c >> 16) & 0xF]; |
929 | |
|
930 | 0 | o2 = nibble2hex[(c >> 12) & 0xF]; |
931 | 0 | o2 <<= 8; |
932 | 0 | o2 |= (u64)nibble2hex[(c >> 8) & 0xF]; |
933 | 0 | o2 <<= 8; |
934 | 0 | o2 |= (u64)nibble2hex[(c >> 4) & 0xF]; |
935 | 0 | o2 <<= 8; |
936 | 0 | o2 |= (u64)nibble2hex[(c >> 0) & 0xF]; |
937 | |
|
938 | 0 | buf_put_be32 (s + 0, o1); |
939 | 0 | buf_put_be32 (s + 4, o2); |
940 | 0 | s += 8; |
941 | 0 | } |
942 | 0 | for (; i < n; i++) |
943 | 0 | { |
944 | 0 | unsigned int c = tmp[i]; |
945 | |
|
946 | 0 | *s++ = nibble2hex[c >> 4]; |
947 | 0 | *s++ = nibble2hex[c & 0xF]; |
948 | 0 | } |
949 | 0 | *s++ = 0; |
950 | 0 | *nwritten = s - buffer; |
951 | 0 | } |
952 | 0 | else |
953 | 0 | { |
954 | 0 | *nwritten = 2*n + extra + negative + 1; |
955 | 0 | } |
956 | 0 | xfree (tmp); |
957 | 0 | return 0; |
958 | 0 | } |
959 | 0 | else |
960 | 0 | return GPG_ERR_INV_ARG; |
961 | 136k | } |
962 | | |
963 | | |
964 | | /* |
965 | | * Like gcry_mpi_print but this function allocates the buffer itself. |
966 | | * The caller has to supply the address of a pointer. NWRITTEN may be |
967 | | * NULL. |
968 | | */ |
969 | | gcry_err_code_t |
970 | | _gcry_mpi_aprint (enum gcry_mpi_format format, |
971 | | unsigned char **buffer, size_t *nwritten, |
972 | | struct gcry_mpi *a) |
973 | 0 | { |
974 | 0 | size_t n; |
975 | 0 | gcry_err_code_t rc; |
976 | |
|
977 | 0 | *buffer = NULL; |
978 | 0 | rc = _gcry_mpi_print (format, NULL, 0, &n, a); |
979 | 0 | if (rc) |
980 | 0 | return rc; |
981 | | |
982 | 0 | *buffer = mpi_is_secure(a) ? xtrymalloc_secure (n?n:1) : xtrymalloc (n?n:1); |
983 | 0 | if (!*buffer) |
984 | 0 | return gpg_err_code_from_syserror (); |
985 | | /* If the returned buffer will have a length of 0, we nevertheless |
986 | | allocated 1 byte (malloc needs it anyway) and store a 0. */ |
987 | 0 | if (!n) |
988 | 0 | **buffer = 0; |
989 | 0 | rc = _gcry_mpi_print( format, *buffer, n, &n, a ); |
990 | 0 | if (rc) |
991 | 0 | { |
992 | 0 | xfree (*buffer); |
993 | 0 | *buffer = NULL; |
994 | 0 | } |
995 | 0 | else if (nwritten) |
996 | 0 | *nwritten = n; |
997 | 0 | return rc; |
998 | 0 | } |
999 | | |
1000 | | |
1001 | | /* Turn VALUE into an octet string and store it in an allocated buffer |
1002 | | at R_FRAME or - if R_RAME is NULL - copy it into the caller |
1003 | | provided buffer SPACE; either SPACE or R_FRAME may be used. If |
1004 | | SPACE if not NULL, the caller must provide a buffer of at least |
1005 | | NBYTES. If the resulting octet string is shorter than NBYTES pad |
1006 | | it to the left with zeroes. If VALUE does not fit into NBYTES |
1007 | | return an error code. */ |
1008 | | gpg_err_code_t |
1009 | | _gcry_mpi_to_octet_string (unsigned char **r_frame, void *space, |
1010 | | gcry_mpi_t value, size_t nbytes) |
1011 | 0 | { |
1012 | 0 | gpg_err_code_t rc; |
1013 | 0 | size_t nframe, noff, n; |
1014 | 0 | unsigned char *frame; |
1015 | |
|
1016 | 0 | if (!r_frame == !space) |
1017 | 0 | return GPG_ERR_INV_ARG; /* Only one may be used. */ |
1018 | | |
1019 | 0 | if (r_frame) |
1020 | 0 | *r_frame = NULL; |
1021 | |
|
1022 | 0 | rc = _gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &nframe, value); |
1023 | 0 | if (rc) |
1024 | 0 | return rc; |
1025 | 0 | if (nframe > nbytes) |
1026 | 0 | return GPG_ERR_TOO_LARGE; /* Value too long to fit into NBYTES. */ |
1027 | | |
1028 | 0 | noff = (nframe < nbytes)? nbytes - nframe : 0; |
1029 | 0 | n = nframe + noff; |
1030 | 0 | if (space) |
1031 | 0 | frame = space; |
1032 | 0 | else |
1033 | 0 | { |
1034 | 0 | frame = mpi_is_secure (value)? xtrymalloc_secure (n) : xtrymalloc (n); |
1035 | 0 | if (!frame) |
1036 | 0 | { |
1037 | 0 | rc = gpg_err_code_from_syserror (); |
1038 | 0 | return rc; |
1039 | 0 | } |
1040 | 0 | } |
1041 | 0 | if (noff) |
1042 | 0 | memset (frame, 0, noff); |
1043 | 0 | nframe += noff; |
1044 | 0 | rc = _gcry_mpi_print (GCRYMPI_FMT_USG, frame+noff, nframe-noff, NULL, value); |
1045 | 0 | if (rc) |
1046 | 0 | { |
1047 | 0 | xfree (frame); |
1048 | 0 | return rc; |
1049 | 0 | } |
1050 | | |
1051 | 0 | if (r_frame) |
1052 | 0 | *r_frame = frame; |
1053 | 0 | return 0; |
1054 | 0 | } |