xref: /linux/lib/crypto/mpi/mpicoder.c (revision a1c613ae4c322ddd58d5a8539dbfba2a0380a8c0)
1*2a598d0bSHerbert Xu /* mpicoder.c  -  Coder for the external representation of MPIs
2*2a598d0bSHerbert Xu  * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
3*2a598d0bSHerbert Xu  *
4*2a598d0bSHerbert Xu  * This file is part of GnuPG.
5*2a598d0bSHerbert Xu  *
6*2a598d0bSHerbert Xu  * GnuPG is free software; you can redistribute it and/or modify
7*2a598d0bSHerbert Xu  * it under the terms of the GNU General Public License as published by
8*2a598d0bSHerbert Xu  * the Free Software Foundation; either version 2 of the License, or
9*2a598d0bSHerbert Xu  * (at your option) any later version.
10*2a598d0bSHerbert Xu  *
11*2a598d0bSHerbert Xu  * GnuPG is distributed in the hope that it will be useful,
12*2a598d0bSHerbert Xu  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*2a598d0bSHerbert Xu  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*2a598d0bSHerbert Xu  * GNU General Public License for more details.
15*2a598d0bSHerbert Xu  *
16*2a598d0bSHerbert Xu  * You should have received a copy of the GNU General Public License
17*2a598d0bSHerbert Xu  * along with this program; if not, write to the Free Software
18*2a598d0bSHerbert Xu  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19*2a598d0bSHerbert Xu  */
20*2a598d0bSHerbert Xu 
21*2a598d0bSHerbert Xu #include <linux/bitops.h>
22*2a598d0bSHerbert Xu #include <linux/count_zeros.h>
23*2a598d0bSHerbert Xu #include <linux/byteorder/generic.h>
24*2a598d0bSHerbert Xu #include <linux/scatterlist.h>
25*2a598d0bSHerbert Xu #include <linux/string.h>
26*2a598d0bSHerbert Xu #include "mpi-internal.h"
27*2a598d0bSHerbert Xu 
28*2a598d0bSHerbert Xu #define MAX_EXTERN_SCAN_BYTES (16*1024*1024)
29*2a598d0bSHerbert Xu #define MAX_EXTERN_MPI_BITS 16384
30*2a598d0bSHerbert Xu 
31*2a598d0bSHerbert Xu /**
32*2a598d0bSHerbert Xu  * mpi_read_raw_data - Read a raw byte stream as a positive integer
33*2a598d0bSHerbert Xu  * @xbuffer: The data to read
34*2a598d0bSHerbert Xu  * @nbytes: The amount of data to read
35*2a598d0bSHerbert Xu  */
mpi_read_raw_data(const void * xbuffer,size_t nbytes)36*2a598d0bSHerbert Xu MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes)
37*2a598d0bSHerbert Xu {
38*2a598d0bSHerbert Xu 	const uint8_t *buffer = xbuffer;
39*2a598d0bSHerbert Xu 	int i, j;
40*2a598d0bSHerbert Xu 	unsigned nbits, nlimbs;
41*2a598d0bSHerbert Xu 	mpi_limb_t a;
42*2a598d0bSHerbert Xu 	MPI val = NULL;
43*2a598d0bSHerbert Xu 
44*2a598d0bSHerbert Xu 	while (nbytes > 0 && buffer[0] == 0) {
45*2a598d0bSHerbert Xu 		buffer++;
46*2a598d0bSHerbert Xu 		nbytes--;
47*2a598d0bSHerbert Xu 	}
48*2a598d0bSHerbert Xu 
49*2a598d0bSHerbert Xu 	nbits = nbytes * 8;
50*2a598d0bSHerbert Xu 	if (nbits > MAX_EXTERN_MPI_BITS) {
51*2a598d0bSHerbert Xu 		pr_info("MPI: mpi too large (%u bits)\n", nbits);
52*2a598d0bSHerbert Xu 		return NULL;
53*2a598d0bSHerbert Xu 	}
54*2a598d0bSHerbert Xu 	if (nbytes > 0)
55*2a598d0bSHerbert Xu 		nbits -= count_leading_zeros(buffer[0]) - (BITS_PER_LONG - 8);
56*2a598d0bSHerbert Xu 
57*2a598d0bSHerbert Xu 	nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB);
58*2a598d0bSHerbert Xu 	val = mpi_alloc(nlimbs);
59*2a598d0bSHerbert Xu 	if (!val)
60*2a598d0bSHerbert Xu 		return NULL;
61*2a598d0bSHerbert Xu 	val->nbits = nbits;
62*2a598d0bSHerbert Xu 	val->sign = 0;
63*2a598d0bSHerbert Xu 	val->nlimbs = nlimbs;
64*2a598d0bSHerbert Xu 
65*2a598d0bSHerbert Xu 	if (nbytes > 0) {
66*2a598d0bSHerbert Xu 		i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
67*2a598d0bSHerbert Xu 		i %= BYTES_PER_MPI_LIMB;
68*2a598d0bSHerbert Xu 		for (j = nlimbs; j > 0; j--) {
69*2a598d0bSHerbert Xu 			a = 0;
70*2a598d0bSHerbert Xu 			for (; i < BYTES_PER_MPI_LIMB; i++) {
71*2a598d0bSHerbert Xu 				a <<= 8;
72*2a598d0bSHerbert Xu 				a |= *buffer++;
73*2a598d0bSHerbert Xu 			}
74*2a598d0bSHerbert Xu 			i = 0;
75*2a598d0bSHerbert Xu 			val->d[j - 1] = a;
76*2a598d0bSHerbert Xu 		}
77*2a598d0bSHerbert Xu 	}
78*2a598d0bSHerbert Xu 	return val;
79*2a598d0bSHerbert Xu }
80*2a598d0bSHerbert Xu EXPORT_SYMBOL_GPL(mpi_read_raw_data);
81*2a598d0bSHerbert Xu 
mpi_read_from_buffer(const void * xbuffer,unsigned * ret_nread)82*2a598d0bSHerbert Xu MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)
83*2a598d0bSHerbert Xu {
84*2a598d0bSHerbert Xu 	const uint8_t *buffer = xbuffer;
85*2a598d0bSHerbert Xu 	unsigned int nbits, nbytes;
86*2a598d0bSHerbert Xu 	MPI val;
87*2a598d0bSHerbert Xu 
88*2a598d0bSHerbert Xu 	if (*ret_nread < 2)
89*2a598d0bSHerbert Xu 		return ERR_PTR(-EINVAL);
90*2a598d0bSHerbert Xu 	nbits = buffer[0] << 8 | buffer[1];
91*2a598d0bSHerbert Xu 
92*2a598d0bSHerbert Xu 	if (nbits > MAX_EXTERN_MPI_BITS) {
93*2a598d0bSHerbert Xu 		pr_info("MPI: mpi too large (%u bits)\n", nbits);
94*2a598d0bSHerbert Xu 		return ERR_PTR(-EINVAL);
95*2a598d0bSHerbert Xu 	}
96*2a598d0bSHerbert Xu 
97*2a598d0bSHerbert Xu 	nbytes = DIV_ROUND_UP(nbits, 8);
98*2a598d0bSHerbert Xu 	if (nbytes + 2 > *ret_nread) {
99*2a598d0bSHerbert Xu 		pr_info("MPI: mpi larger than buffer nbytes=%u ret_nread=%u\n",
100*2a598d0bSHerbert Xu 				nbytes, *ret_nread);
101*2a598d0bSHerbert Xu 		return ERR_PTR(-EINVAL);
102*2a598d0bSHerbert Xu 	}
103*2a598d0bSHerbert Xu 
104*2a598d0bSHerbert Xu 	val = mpi_read_raw_data(buffer + 2, nbytes);
105*2a598d0bSHerbert Xu 	if (!val)
106*2a598d0bSHerbert Xu 		return ERR_PTR(-ENOMEM);
107*2a598d0bSHerbert Xu 
108*2a598d0bSHerbert Xu 	*ret_nread = nbytes + 2;
109*2a598d0bSHerbert Xu 	return val;
110*2a598d0bSHerbert Xu }
111*2a598d0bSHerbert Xu EXPORT_SYMBOL_GPL(mpi_read_from_buffer);
112*2a598d0bSHerbert Xu 
113*2a598d0bSHerbert Xu /****************
114*2a598d0bSHerbert Xu  * Fill the mpi VAL from the hex string in STR.
115*2a598d0bSHerbert Xu  */
mpi_fromstr(MPI val,const char * str)116*2a598d0bSHerbert Xu int mpi_fromstr(MPI val, const char *str)
117*2a598d0bSHerbert Xu {
118*2a598d0bSHerbert Xu 	int sign = 0;
119*2a598d0bSHerbert Xu 	int prepend_zero = 0;
120*2a598d0bSHerbert Xu 	int i, j, c, c1, c2;
121*2a598d0bSHerbert Xu 	unsigned int nbits, nbytes, nlimbs;
122*2a598d0bSHerbert Xu 	mpi_limb_t a;
123*2a598d0bSHerbert Xu 
124*2a598d0bSHerbert Xu 	if (*str == '-') {
125*2a598d0bSHerbert Xu 		sign = 1;
126*2a598d0bSHerbert Xu 		str++;
127*2a598d0bSHerbert Xu 	}
128*2a598d0bSHerbert Xu 
129*2a598d0bSHerbert Xu 	/* Skip optional hex prefix.  */
130*2a598d0bSHerbert Xu 	if (*str == '0' && str[1] == 'x')
131*2a598d0bSHerbert Xu 		str += 2;
132*2a598d0bSHerbert Xu 
133*2a598d0bSHerbert Xu 	nbits = strlen(str);
134*2a598d0bSHerbert Xu 	if (nbits > MAX_EXTERN_SCAN_BYTES) {
135*2a598d0bSHerbert Xu 		mpi_clear(val);
136*2a598d0bSHerbert Xu 		return -EINVAL;
137*2a598d0bSHerbert Xu 	}
138*2a598d0bSHerbert Xu 	nbits *= 4;
139*2a598d0bSHerbert Xu 	if ((nbits % 8))
140*2a598d0bSHerbert Xu 		prepend_zero = 1;
141*2a598d0bSHerbert Xu 
142*2a598d0bSHerbert Xu 	nbytes = (nbits+7) / 8;
143*2a598d0bSHerbert Xu 	nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
144*2a598d0bSHerbert Xu 
145*2a598d0bSHerbert Xu 	if (val->alloced < nlimbs)
146*2a598d0bSHerbert Xu 		mpi_resize(val, nlimbs);
147*2a598d0bSHerbert Xu 
148*2a598d0bSHerbert Xu 	i = BYTES_PER_MPI_LIMB - (nbytes % BYTES_PER_MPI_LIMB);
149*2a598d0bSHerbert Xu 	i %= BYTES_PER_MPI_LIMB;
150*2a598d0bSHerbert Xu 	j = val->nlimbs = nlimbs;
151*2a598d0bSHerbert Xu 	val->sign = sign;
152*2a598d0bSHerbert Xu 	for (; j > 0; j--) {
153*2a598d0bSHerbert Xu 		a = 0;
154*2a598d0bSHerbert Xu 		for (; i < BYTES_PER_MPI_LIMB; i++) {
155*2a598d0bSHerbert Xu 			if (prepend_zero) {
156*2a598d0bSHerbert Xu 				c1 = '0';
157*2a598d0bSHerbert Xu 				prepend_zero = 0;
158*2a598d0bSHerbert Xu 			} else
159*2a598d0bSHerbert Xu 				c1 = *str++;
160*2a598d0bSHerbert Xu 
161*2a598d0bSHerbert Xu 			if (!c1) {
162*2a598d0bSHerbert Xu 				mpi_clear(val);
163*2a598d0bSHerbert Xu 				return -EINVAL;
164*2a598d0bSHerbert Xu 			}
165*2a598d0bSHerbert Xu 			c2 = *str++;
166*2a598d0bSHerbert Xu 			if (!c2) {
167*2a598d0bSHerbert Xu 				mpi_clear(val);
168*2a598d0bSHerbert Xu 				return -EINVAL;
169*2a598d0bSHerbert Xu 			}
170*2a598d0bSHerbert Xu 			if (c1 >= '0' && c1 <= '9')
171*2a598d0bSHerbert Xu 				c = c1 - '0';
172*2a598d0bSHerbert Xu 			else if (c1 >= 'a' && c1 <= 'f')
173*2a598d0bSHerbert Xu 				c = c1 - 'a' + 10;
174*2a598d0bSHerbert Xu 			else if (c1 >= 'A' && c1 <= 'F')
175*2a598d0bSHerbert Xu 				c = c1 - 'A' + 10;
176*2a598d0bSHerbert Xu 			else {
177*2a598d0bSHerbert Xu 				mpi_clear(val);
178*2a598d0bSHerbert Xu 				return -EINVAL;
179*2a598d0bSHerbert Xu 			}
180*2a598d0bSHerbert Xu 			c <<= 4;
181*2a598d0bSHerbert Xu 			if (c2 >= '0' && c2 <= '9')
182*2a598d0bSHerbert Xu 				c |= c2 - '0';
183*2a598d0bSHerbert Xu 			else if (c2 >= 'a' && c2 <= 'f')
184*2a598d0bSHerbert Xu 				c |= c2 - 'a' + 10;
185*2a598d0bSHerbert Xu 			else if (c2 >= 'A' && c2 <= 'F')
186*2a598d0bSHerbert Xu 				c |= c2 - 'A' + 10;
187*2a598d0bSHerbert Xu 			else {
188*2a598d0bSHerbert Xu 				mpi_clear(val);
189*2a598d0bSHerbert Xu 				return -EINVAL;
190*2a598d0bSHerbert Xu 			}
191*2a598d0bSHerbert Xu 			a <<= 8;
192*2a598d0bSHerbert Xu 			a |= c;
193*2a598d0bSHerbert Xu 		}
194*2a598d0bSHerbert Xu 		i = 0;
195*2a598d0bSHerbert Xu 		val->d[j-1] = a;
196*2a598d0bSHerbert Xu 	}
197*2a598d0bSHerbert Xu 
198*2a598d0bSHerbert Xu 	return 0;
199*2a598d0bSHerbert Xu }
200*2a598d0bSHerbert Xu EXPORT_SYMBOL_GPL(mpi_fromstr);
201*2a598d0bSHerbert Xu 
mpi_scanval(const char * string)202*2a598d0bSHerbert Xu MPI mpi_scanval(const char *string)
203*2a598d0bSHerbert Xu {
204*2a598d0bSHerbert Xu 	MPI a;
205*2a598d0bSHerbert Xu 
206*2a598d0bSHerbert Xu 	a = mpi_alloc(0);
207*2a598d0bSHerbert Xu 	if (!a)
208*2a598d0bSHerbert Xu 		return NULL;
209*2a598d0bSHerbert Xu 
210*2a598d0bSHerbert Xu 	if (mpi_fromstr(a, string)) {
211*2a598d0bSHerbert Xu 		mpi_free(a);
212*2a598d0bSHerbert Xu 		return NULL;
213*2a598d0bSHerbert Xu 	}
214*2a598d0bSHerbert Xu 	mpi_normalize(a);
215*2a598d0bSHerbert Xu 	return a;
216*2a598d0bSHerbert Xu }
217*2a598d0bSHerbert Xu EXPORT_SYMBOL_GPL(mpi_scanval);
218*2a598d0bSHerbert Xu 
count_lzeros(MPI a)219*2a598d0bSHerbert Xu static int count_lzeros(MPI a)
220*2a598d0bSHerbert Xu {
221*2a598d0bSHerbert Xu 	mpi_limb_t alimb;
222*2a598d0bSHerbert Xu 	int i, lzeros = 0;
223*2a598d0bSHerbert Xu 
224*2a598d0bSHerbert Xu 	for (i = a->nlimbs - 1; i >= 0; i--) {
225*2a598d0bSHerbert Xu 		alimb = a->d[i];
226*2a598d0bSHerbert Xu 		if (alimb == 0) {
227*2a598d0bSHerbert Xu 			lzeros += sizeof(mpi_limb_t);
228*2a598d0bSHerbert Xu 		} else {
229*2a598d0bSHerbert Xu 			lzeros += count_leading_zeros(alimb) / 8;
230*2a598d0bSHerbert Xu 			break;
231*2a598d0bSHerbert Xu 		}
232*2a598d0bSHerbert Xu 	}
233*2a598d0bSHerbert Xu 	return lzeros;
234*2a598d0bSHerbert Xu }
235*2a598d0bSHerbert Xu 
236*2a598d0bSHerbert Xu /**
237*2a598d0bSHerbert Xu  * mpi_read_buffer() - read MPI to a buffer provided by user (msb first)
238*2a598d0bSHerbert Xu  *
239*2a598d0bSHerbert Xu  * @a:		a multi precision integer
240*2a598d0bSHerbert Xu  * @buf:	buffer to which the output will be written to. Needs to be at
241*2a598d0bSHerbert Xu  *		least mpi_get_size(a) long.
242*2a598d0bSHerbert Xu  * @buf_len:	size of the buf.
243*2a598d0bSHerbert Xu  * @nbytes:	receives the actual length of the data written on success and
244*2a598d0bSHerbert Xu  *		the data to-be-written on -EOVERFLOW in case buf_len was too
245*2a598d0bSHerbert Xu  *		small.
246*2a598d0bSHerbert Xu  * @sign:	if not NULL, it will be set to the sign of a.
247*2a598d0bSHerbert Xu  *
248*2a598d0bSHerbert Xu  * Return:	0 on success or error code in case of error
249*2a598d0bSHerbert Xu  */
mpi_read_buffer(MPI a,uint8_t * buf,unsigned buf_len,unsigned * nbytes,int * sign)250*2a598d0bSHerbert Xu int mpi_read_buffer(MPI a, uint8_t *buf, unsigned buf_len, unsigned *nbytes,
251*2a598d0bSHerbert Xu 		    int *sign)
252*2a598d0bSHerbert Xu {
253*2a598d0bSHerbert Xu 	uint8_t *p;
254*2a598d0bSHerbert Xu #if BYTES_PER_MPI_LIMB == 4
255*2a598d0bSHerbert Xu 	__be32 alimb;
256*2a598d0bSHerbert Xu #elif BYTES_PER_MPI_LIMB == 8
257*2a598d0bSHerbert Xu 	__be64 alimb;
258*2a598d0bSHerbert Xu #else
259*2a598d0bSHerbert Xu #error please implement for this limb size.
260*2a598d0bSHerbert Xu #endif
261*2a598d0bSHerbert Xu 	unsigned int n = mpi_get_size(a);
262*2a598d0bSHerbert Xu 	int i, lzeros;
263*2a598d0bSHerbert Xu 
264*2a598d0bSHerbert Xu 	if (!buf || !nbytes)
265*2a598d0bSHerbert Xu 		return -EINVAL;
266*2a598d0bSHerbert Xu 
267*2a598d0bSHerbert Xu 	if (sign)
268*2a598d0bSHerbert Xu 		*sign = a->sign;
269*2a598d0bSHerbert Xu 
270*2a598d0bSHerbert Xu 	lzeros = count_lzeros(a);
271*2a598d0bSHerbert Xu 
272*2a598d0bSHerbert Xu 	if (buf_len < n - lzeros) {
273*2a598d0bSHerbert Xu 		*nbytes = n - lzeros;
274*2a598d0bSHerbert Xu 		return -EOVERFLOW;
275*2a598d0bSHerbert Xu 	}
276*2a598d0bSHerbert Xu 
277*2a598d0bSHerbert Xu 	p = buf;
278*2a598d0bSHerbert Xu 	*nbytes = n - lzeros;
279*2a598d0bSHerbert Xu 
280*2a598d0bSHerbert Xu 	for (i = a->nlimbs - 1 - lzeros / BYTES_PER_MPI_LIMB,
281*2a598d0bSHerbert Xu 			lzeros %= BYTES_PER_MPI_LIMB;
282*2a598d0bSHerbert Xu 		i >= 0; i--) {
283*2a598d0bSHerbert Xu #if BYTES_PER_MPI_LIMB == 4
284*2a598d0bSHerbert Xu 		alimb = cpu_to_be32(a->d[i]);
285*2a598d0bSHerbert Xu #elif BYTES_PER_MPI_LIMB == 8
286*2a598d0bSHerbert Xu 		alimb = cpu_to_be64(a->d[i]);
287*2a598d0bSHerbert Xu #else
288*2a598d0bSHerbert Xu #error please implement for this limb size.
289*2a598d0bSHerbert Xu #endif
290*2a598d0bSHerbert Xu 		memcpy(p, (u8 *)&alimb + lzeros, BYTES_PER_MPI_LIMB - lzeros);
291*2a598d0bSHerbert Xu 		p += BYTES_PER_MPI_LIMB - lzeros;
292*2a598d0bSHerbert Xu 		lzeros = 0;
293*2a598d0bSHerbert Xu 	}
294*2a598d0bSHerbert Xu 	return 0;
295*2a598d0bSHerbert Xu }
296*2a598d0bSHerbert Xu EXPORT_SYMBOL_GPL(mpi_read_buffer);
297*2a598d0bSHerbert Xu 
298*2a598d0bSHerbert Xu /*
299*2a598d0bSHerbert Xu  * mpi_get_buffer() - Returns an allocated buffer with the MPI (msb first).
300*2a598d0bSHerbert Xu  * Caller must free the return string.
301*2a598d0bSHerbert Xu  * This function does return a 0 byte buffer with nbytes set to zero if the
302*2a598d0bSHerbert Xu  * value of A is zero.
303*2a598d0bSHerbert Xu  *
304*2a598d0bSHerbert Xu  * @a:		a multi precision integer.
305*2a598d0bSHerbert Xu  * @nbytes:	receives the length of this buffer.
306*2a598d0bSHerbert Xu  * @sign:	if not NULL, it will be set to the sign of the a.
307*2a598d0bSHerbert Xu  *
308*2a598d0bSHerbert Xu  * Return:	Pointer to MPI buffer or NULL on error
309*2a598d0bSHerbert Xu  */
mpi_get_buffer(MPI a,unsigned * nbytes,int * sign)310*2a598d0bSHerbert Xu void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign)
311*2a598d0bSHerbert Xu {
312*2a598d0bSHerbert Xu 	uint8_t *buf;
313*2a598d0bSHerbert Xu 	unsigned int n;
314*2a598d0bSHerbert Xu 	int ret;
315*2a598d0bSHerbert Xu 
316*2a598d0bSHerbert Xu 	if (!nbytes)
317*2a598d0bSHerbert Xu 		return NULL;
318*2a598d0bSHerbert Xu 
319*2a598d0bSHerbert Xu 	n = mpi_get_size(a);
320*2a598d0bSHerbert Xu 
321*2a598d0bSHerbert Xu 	if (!n)
322*2a598d0bSHerbert Xu 		n++;
323*2a598d0bSHerbert Xu 
324*2a598d0bSHerbert Xu 	buf = kmalloc(n, GFP_KERNEL);
325*2a598d0bSHerbert Xu 
326*2a598d0bSHerbert Xu 	if (!buf)
327*2a598d0bSHerbert Xu 		return NULL;
328*2a598d0bSHerbert Xu 
329*2a598d0bSHerbert Xu 	ret = mpi_read_buffer(a, buf, n, nbytes, sign);
330*2a598d0bSHerbert Xu 
331*2a598d0bSHerbert Xu 	if (ret) {
332*2a598d0bSHerbert Xu 		kfree(buf);
333*2a598d0bSHerbert Xu 		return NULL;
334*2a598d0bSHerbert Xu 	}
335*2a598d0bSHerbert Xu 	return buf;
336*2a598d0bSHerbert Xu }
337*2a598d0bSHerbert Xu EXPORT_SYMBOL_GPL(mpi_get_buffer);
338*2a598d0bSHerbert Xu 
339*2a598d0bSHerbert Xu /**
340*2a598d0bSHerbert Xu  * mpi_write_to_sgl() - Funnction exports MPI to an sgl (msb first)
341*2a598d0bSHerbert Xu  *
342*2a598d0bSHerbert Xu  * This function works in the same way as the mpi_read_buffer, but it
343*2a598d0bSHerbert Xu  * takes an sgl instead of u8 * buf.
344*2a598d0bSHerbert Xu  *
345*2a598d0bSHerbert Xu  * @a:		a multi precision integer
346*2a598d0bSHerbert Xu  * @sgl:	scatterlist to write to. Needs to be at least
347*2a598d0bSHerbert Xu  *		mpi_get_size(a) long.
348*2a598d0bSHerbert Xu  * @nbytes:	the number of bytes to write.  Leading bytes will be
349*2a598d0bSHerbert Xu  *		filled with zero.
350*2a598d0bSHerbert Xu  * @sign:	if not NULL, it will be set to the sign of a.
351*2a598d0bSHerbert Xu  *
352*2a598d0bSHerbert Xu  * Return:	0 on success or error code in case of error
353*2a598d0bSHerbert Xu  */
mpi_write_to_sgl(MPI a,struct scatterlist * sgl,unsigned nbytes,int * sign)354*2a598d0bSHerbert Xu int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned nbytes,
355*2a598d0bSHerbert Xu 		     int *sign)
356*2a598d0bSHerbert Xu {
357*2a598d0bSHerbert Xu 	u8 *p, *p2;
358*2a598d0bSHerbert Xu #if BYTES_PER_MPI_LIMB == 4
359*2a598d0bSHerbert Xu 	__be32 alimb;
360*2a598d0bSHerbert Xu #elif BYTES_PER_MPI_LIMB == 8
361*2a598d0bSHerbert Xu 	__be64 alimb;
362*2a598d0bSHerbert Xu #else
363*2a598d0bSHerbert Xu #error please implement for this limb size.
364*2a598d0bSHerbert Xu #endif
365*2a598d0bSHerbert Xu 	unsigned int n = mpi_get_size(a);
366*2a598d0bSHerbert Xu 	struct sg_mapping_iter miter;
367*2a598d0bSHerbert Xu 	int i, x, buf_len;
368*2a598d0bSHerbert Xu 	int nents;
369*2a598d0bSHerbert Xu 
370*2a598d0bSHerbert Xu 	if (sign)
371*2a598d0bSHerbert Xu 		*sign = a->sign;
372*2a598d0bSHerbert Xu 
373*2a598d0bSHerbert Xu 	if (nbytes < n)
374*2a598d0bSHerbert Xu 		return -EOVERFLOW;
375*2a598d0bSHerbert Xu 
376*2a598d0bSHerbert Xu 	nents = sg_nents_for_len(sgl, nbytes);
377*2a598d0bSHerbert Xu 	if (nents < 0)
378*2a598d0bSHerbert Xu 		return -EINVAL;
379*2a598d0bSHerbert Xu 
380*2a598d0bSHerbert Xu 	sg_miter_start(&miter, sgl, nents, SG_MITER_ATOMIC | SG_MITER_TO_SG);
381*2a598d0bSHerbert Xu 	sg_miter_next(&miter);
382*2a598d0bSHerbert Xu 	buf_len = miter.length;
383*2a598d0bSHerbert Xu 	p2 = miter.addr;
384*2a598d0bSHerbert Xu 
385*2a598d0bSHerbert Xu 	while (nbytes > n) {
386*2a598d0bSHerbert Xu 		i = min_t(unsigned, nbytes - n, buf_len);
387*2a598d0bSHerbert Xu 		memset(p2, 0, i);
388*2a598d0bSHerbert Xu 		p2 += i;
389*2a598d0bSHerbert Xu 		nbytes -= i;
390*2a598d0bSHerbert Xu 
391*2a598d0bSHerbert Xu 		buf_len -= i;
392*2a598d0bSHerbert Xu 		if (!buf_len) {
393*2a598d0bSHerbert Xu 			sg_miter_next(&miter);
394*2a598d0bSHerbert Xu 			buf_len = miter.length;
395*2a598d0bSHerbert Xu 			p2 = miter.addr;
396*2a598d0bSHerbert Xu 		}
397*2a598d0bSHerbert Xu 	}
398*2a598d0bSHerbert Xu 
399*2a598d0bSHerbert Xu 	for (i = a->nlimbs - 1; i >= 0; i--) {
400*2a598d0bSHerbert Xu #if BYTES_PER_MPI_LIMB == 4
401*2a598d0bSHerbert Xu 		alimb = a->d[i] ? cpu_to_be32(a->d[i]) : 0;
402*2a598d0bSHerbert Xu #elif BYTES_PER_MPI_LIMB == 8
403*2a598d0bSHerbert Xu 		alimb = a->d[i] ? cpu_to_be64(a->d[i]) : 0;
404*2a598d0bSHerbert Xu #else
405*2a598d0bSHerbert Xu #error please implement for this limb size.
406*2a598d0bSHerbert Xu #endif
407*2a598d0bSHerbert Xu 		p = (u8 *)&alimb;
408*2a598d0bSHerbert Xu 
409*2a598d0bSHerbert Xu 		for (x = 0; x < sizeof(alimb); x++) {
410*2a598d0bSHerbert Xu 			*p2++ = *p++;
411*2a598d0bSHerbert Xu 			if (!--buf_len) {
412*2a598d0bSHerbert Xu 				sg_miter_next(&miter);
413*2a598d0bSHerbert Xu 				buf_len = miter.length;
414*2a598d0bSHerbert Xu 				p2 = miter.addr;
415*2a598d0bSHerbert Xu 			}
416*2a598d0bSHerbert Xu 		}
417*2a598d0bSHerbert Xu 	}
418*2a598d0bSHerbert Xu 
419*2a598d0bSHerbert Xu 	sg_miter_stop(&miter);
420*2a598d0bSHerbert Xu 	return 0;
421*2a598d0bSHerbert Xu }
422*2a598d0bSHerbert Xu EXPORT_SYMBOL_GPL(mpi_write_to_sgl);
423*2a598d0bSHerbert Xu 
424*2a598d0bSHerbert Xu /*
425*2a598d0bSHerbert Xu  * mpi_read_raw_from_sgl() - Function allocates an MPI and populates it with
426*2a598d0bSHerbert Xu  *			     data from the sgl
427*2a598d0bSHerbert Xu  *
428*2a598d0bSHerbert Xu  * This function works in the same way as the mpi_read_raw_data, but it
429*2a598d0bSHerbert Xu  * takes an sgl instead of void * buffer. i.e. it allocates
430*2a598d0bSHerbert Xu  * a new MPI and reads the content of the sgl to the MPI.
431*2a598d0bSHerbert Xu  *
432*2a598d0bSHerbert Xu  * @sgl:	scatterlist to read from
433*2a598d0bSHerbert Xu  * @nbytes:	number of bytes to read
434*2a598d0bSHerbert Xu  *
435*2a598d0bSHerbert Xu  * Return:	Pointer to a new MPI or NULL on error
436*2a598d0bSHerbert Xu  */
mpi_read_raw_from_sgl(struct scatterlist * sgl,unsigned int nbytes)437*2a598d0bSHerbert Xu MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes)
438*2a598d0bSHerbert Xu {
439*2a598d0bSHerbert Xu 	struct sg_mapping_iter miter;
440*2a598d0bSHerbert Xu 	unsigned int nbits, nlimbs;
441*2a598d0bSHerbert Xu 	int x, j, z, lzeros, ents;
442*2a598d0bSHerbert Xu 	unsigned int len;
443*2a598d0bSHerbert Xu 	const u8 *buff;
444*2a598d0bSHerbert Xu 	mpi_limb_t a;
445*2a598d0bSHerbert Xu 	MPI val = NULL;
446*2a598d0bSHerbert Xu 
447*2a598d0bSHerbert Xu 	ents = sg_nents_for_len(sgl, nbytes);
448*2a598d0bSHerbert Xu 	if (ents < 0)
449*2a598d0bSHerbert Xu 		return NULL;
450*2a598d0bSHerbert Xu 
451*2a598d0bSHerbert Xu 	sg_miter_start(&miter, sgl, ents, SG_MITER_ATOMIC | SG_MITER_FROM_SG);
452*2a598d0bSHerbert Xu 
453*2a598d0bSHerbert Xu 	lzeros = 0;
454*2a598d0bSHerbert Xu 	len = 0;
455*2a598d0bSHerbert Xu 	while (nbytes > 0) {
456*2a598d0bSHerbert Xu 		while (len && !*buff) {
457*2a598d0bSHerbert Xu 			lzeros++;
458*2a598d0bSHerbert Xu 			len--;
459*2a598d0bSHerbert Xu 			buff++;
460*2a598d0bSHerbert Xu 		}
461*2a598d0bSHerbert Xu 
462*2a598d0bSHerbert Xu 		if (len && *buff)
463*2a598d0bSHerbert Xu 			break;
464*2a598d0bSHerbert Xu 
465*2a598d0bSHerbert Xu 		sg_miter_next(&miter);
466*2a598d0bSHerbert Xu 		buff = miter.addr;
467*2a598d0bSHerbert Xu 		len = miter.length;
468*2a598d0bSHerbert Xu 
469*2a598d0bSHerbert Xu 		nbytes -= lzeros;
470*2a598d0bSHerbert Xu 		lzeros = 0;
471*2a598d0bSHerbert Xu 	}
472*2a598d0bSHerbert Xu 
473*2a598d0bSHerbert Xu 	miter.consumed = lzeros;
474*2a598d0bSHerbert Xu 
475*2a598d0bSHerbert Xu 	nbytes -= lzeros;
476*2a598d0bSHerbert Xu 	nbits = nbytes * 8;
477*2a598d0bSHerbert Xu 	if (nbits > MAX_EXTERN_MPI_BITS) {
478*2a598d0bSHerbert Xu 		sg_miter_stop(&miter);
479*2a598d0bSHerbert Xu 		pr_info("MPI: mpi too large (%u bits)\n", nbits);
480*2a598d0bSHerbert Xu 		return NULL;
481*2a598d0bSHerbert Xu 	}
482*2a598d0bSHerbert Xu 
483*2a598d0bSHerbert Xu 	if (nbytes > 0)
484*2a598d0bSHerbert Xu 		nbits -= count_leading_zeros(*buff) - (BITS_PER_LONG - 8);
485*2a598d0bSHerbert Xu 
486*2a598d0bSHerbert Xu 	sg_miter_stop(&miter);
487*2a598d0bSHerbert Xu 
488*2a598d0bSHerbert Xu 	nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB);
489*2a598d0bSHerbert Xu 	val = mpi_alloc(nlimbs);
490*2a598d0bSHerbert Xu 	if (!val)
491*2a598d0bSHerbert Xu 		return NULL;
492*2a598d0bSHerbert Xu 
493*2a598d0bSHerbert Xu 	val->nbits = nbits;
494*2a598d0bSHerbert Xu 	val->sign = 0;
495*2a598d0bSHerbert Xu 	val->nlimbs = nlimbs;
496*2a598d0bSHerbert Xu 
497*2a598d0bSHerbert Xu 	if (nbytes == 0)
498*2a598d0bSHerbert Xu 		return val;
499*2a598d0bSHerbert Xu 
500*2a598d0bSHerbert Xu 	j = nlimbs - 1;
501*2a598d0bSHerbert Xu 	a = 0;
502*2a598d0bSHerbert Xu 	z = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
503*2a598d0bSHerbert Xu 	z %= BYTES_PER_MPI_LIMB;
504*2a598d0bSHerbert Xu 
505*2a598d0bSHerbert Xu 	while (sg_miter_next(&miter)) {
506*2a598d0bSHerbert Xu 		buff = miter.addr;
507*2a598d0bSHerbert Xu 		len = min_t(unsigned, miter.length, nbytes);
508*2a598d0bSHerbert Xu 		nbytes -= len;
509*2a598d0bSHerbert Xu 
510*2a598d0bSHerbert Xu 		for (x = 0; x < len; x++) {
511*2a598d0bSHerbert Xu 			a <<= 8;
512*2a598d0bSHerbert Xu 			a |= *buff++;
513*2a598d0bSHerbert Xu 			if (((z + x + 1) % BYTES_PER_MPI_LIMB) == 0) {
514*2a598d0bSHerbert Xu 				val->d[j--] = a;
515*2a598d0bSHerbert Xu 				a = 0;
516*2a598d0bSHerbert Xu 			}
517*2a598d0bSHerbert Xu 		}
518*2a598d0bSHerbert Xu 		z += x;
519*2a598d0bSHerbert Xu 	}
520*2a598d0bSHerbert Xu 
521*2a598d0bSHerbert Xu 	return val;
522*2a598d0bSHerbert Xu }
523*2a598d0bSHerbert Xu EXPORT_SYMBOL_GPL(mpi_read_raw_from_sgl);
524*2a598d0bSHerbert Xu 
525*2a598d0bSHerbert Xu /* Perform a two's complement operation on buffer P of size N bytes.  */
twocompl(unsigned char * p,unsigned int n)526*2a598d0bSHerbert Xu static void twocompl(unsigned char *p, unsigned int n)
527*2a598d0bSHerbert Xu {
528*2a598d0bSHerbert Xu 	int i;
529*2a598d0bSHerbert Xu 
530*2a598d0bSHerbert Xu 	for (i = n-1; i >= 0 && !p[i]; i--)
531*2a598d0bSHerbert Xu 		;
532*2a598d0bSHerbert Xu 	if (i >= 0) {
533*2a598d0bSHerbert Xu 		if ((p[i] & 0x01))
534*2a598d0bSHerbert Xu 			p[i] = (((p[i] ^ 0xfe) | 0x01) & 0xff);
535*2a598d0bSHerbert Xu 		else if ((p[i] & 0x02))
536*2a598d0bSHerbert Xu 			p[i] = (((p[i] ^ 0xfc) | 0x02) & 0xfe);
537*2a598d0bSHerbert Xu 		else if ((p[i] & 0x04))
538*2a598d0bSHerbert Xu 			p[i] = (((p[i] ^ 0xf8) | 0x04) & 0xfc);
539*2a598d0bSHerbert Xu 		else if ((p[i] & 0x08))
540*2a598d0bSHerbert Xu 			p[i] = (((p[i] ^ 0xf0) | 0x08) & 0xf8);
541*2a598d0bSHerbert Xu 		else if ((p[i] & 0x10))
542*2a598d0bSHerbert Xu 			p[i] = (((p[i] ^ 0xe0) | 0x10) & 0xf0);
543*2a598d0bSHerbert Xu 		else if ((p[i] & 0x20))
544*2a598d0bSHerbert Xu 			p[i] = (((p[i] ^ 0xc0) | 0x20) & 0xe0);
545*2a598d0bSHerbert Xu 		else if ((p[i] & 0x40))
546*2a598d0bSHerbert Xu 			p[i] = (((p[i] ^ 0x80) | 0x40) & 0xc0);
547*2a598d0bSHerbert Xu 		else
548*2a598d0bSHerbert Xu 			p[i] = 0x80;
549*2a598d0bSHerbert Xu 
550*2a598d0bSHerbert Xu 		for (i--; i >= 0; i--)
551*2a598d0bSHerbert Xu 			p[i] ^= 0xff;
552*2a598d0bSHerbert Xu 	}
553*2a598d0bSHerbert Xu }
554*2a598d0bSHerbert Xu 
mpi_print(enum gcry_mpi_format format,unsigned char * buffer,size_t buflen,size_t * nwritten,MPI a)555*2a598d0bSHerbert Xu int mpi_print(enum gcry_mpi_format format, unsigned char *buffer,
556*2a598d0bSHerbert Xu 			size_t buflen, size_t *nwritten, MPI a)
557*2a598d0bSHerbert Xu {
558*2a598d0bSHerbert Xu 	unsigned int nbits = mpi_get_nbits(a);
559*2a598d0bSHerbert Xu 	size_t len;
560*2a598d0bSHerbert Xu 	size_t dummy_nwritten;
561*2a598d0bSHerbert Xu 	int negative;
562*2a598d0bSHerbert Xu 
563*2a598d0bSHerbert Xu 	if (!nwritten)
564*2a598d0bSHerbert Xu 		nwritten = &dummy_nwritten;
565*2a598d0bSHerbert Xu 
566*2a598d0bSHerbert Xu 	/* Libgcrypt does no always care to set clear the sign if the value
567*2a598d0bSHerbert Xu 	 * is 0.  For printing this is a bit of a surprise, in particular
568*2a598d0bSHerbert Xu 	 * because if some of the formats don't support negative numbers but
569*2a598d0bSHerbert Xu 	 * should be able to print a zero.  Thus we need this extra test
570*2a598d0bSHerbert Xu 	 * for a negative number.
571*2a598d0bSHerbert Xu 	 */
572*2a598d0bSHerbert Xu 	if (a->sign && mpi_cmp_ui(a, 0))
573*2a598d0bSHerbert Xu 		negative = 1;
574*2a598d0bSHerbert Xu 	else
575*2a598d0bSHerbert Xu 		negative = 0;
576*2a598d0bSHerbert Xu 
577*2a598d0bSHerbert Xu 	len = buflen;
578*2a598d0bSHerbert Xu 	*nwritten = 0;
579*2a598d0bSHerbert Xu 	if (format == GCRYMPI_FMT_STD) {
580*2a598d0bSHerbert Xu 		unsigned char *tmp;
581*2a598d0bSHerbert Xu 		int extra = 0;
582*2a598d0bSHerbert Xu 		unsigned int n;
583*2a598d0bSHerbert Xu 
584*2a598d0bSHerbert Xu 		tmp = mpi_get_buffer(a, &n, NULL);
585*2a598d0bSHerbert Xu 		if (!tmp)
586*2a598d0bSHerbert Xu 			return -EINVAL;
587*2a598d0bSHerbert Xu 
588*2a598d0bSHerbert Xu 		if (negative) {
589*2a598d0bSHerbert Xu 			twocompl(tmp, n);
590*2a598d0bSHerbert Xu 			if (!(*tmp & 0x80)) {
591*2a598d0bSHerbert Xu 				/* Need to extend the sign.  */
592*2a598d0bSHerbert Xu 				n++;
593*2a598d0bSHerbert Xu 				extra = 2;
594*2a598d0bSHerbert Xu 			}
595*2a598d0bSHerbert Xu 		} else if (n && (*tmp & 0x80)) {
596*2a598d0bSHerbert Xu 			/* Positive but the high bit of the returned buffer is set.
597*2a598d0bSHerbert Xu 			 * Thus we need to print an extra leading 0x00 so that the
598*2a598d0bSHerbert Xu 			 * output is interpreted as a positive number.
599*2a598d0bSHerbert Xu 			 */
600*2a598d0bSHerbert Xu 			n++;
601*2a598d0bSHerbert Xu 			extra = 1;
602*2a598d0bSHerbert Xu 		}
603*2a598d0bSHerbert Xu 
604*2a598d0bSHerbert Xu 		if (buffer && n > len) {
605*2a598d0bSHerbert Xu 			/* The provided buffer is too short. */
606*2a598d0bSHerbert Xu 			kfree(tmp);
607*2a598d0bSHerbert Xu 			return -E2BIG;
608*2a598d0bSHerbert Xu 		}
609*2a598d0bSHerbert Xu 		if (buffer) {
610*2a598d0bSHerbert Xu 			unsigned char *s = buffer;
611*2a598d0bSHerbert Xu 
612*2a598d0bSHerbert Xu 			if (extra == 1)
613*2a598d0bSHerbert Xu 				*s++ = 0;
614*2a598d0bSHerbert Xu 			else if (extra)
615*2a598d0bSHerbert Xu 				*s++ = 0xff;
616*2a598d0bSHerbert Xu 			memcpy(s, tmp, n-!!extra);
617*2a598d0bSHerbert Xu 		}
618*2a598d0bSHerbert Xu 		kfree(tmp);
619*2a598d0bSHerbert Xu 		*nwritten = n;
620*2a598d0bSHerbert Xu 		return 0;
621*2a598d0bSHerbert Xu 	} else if (format == GCRYMPI_FMT_USG) {
622*2a598d0bSHerbert Xu 		unsigned int n = (nbits + 7)/8;
623*2a598d0bSHerbert Xu 
624*2a598d0bSHerbert Xu 		/* Note:  We ignore the sign for this format.  */
625*2a598d0bSHerbert Xu 		/* FIXME: for performance reasons we should put this into
626*2a598d0bSHerbert Xu 		 * mpi_aprint because we can then use the buffer directly.
627*2a598d0bSHerbert Xu 		 */
628*2a598d0bSHerbert Xu 
629*2a598d0bSHerbert Xu 		if (buffer && n > len)
630*2a598d0bSHerbert Xu 			return -E2BIG;
631*2a598d0bSHerbert Xu 		if (buffer) {
632*2a598d0bSHerbert Xu 			unsigned char *tmp;
633*2a598d0bSHerbert Xu 
634*2a598d0bSHerbert Xu 			tmp = mpi_get_buffer(a, &n, NULL);
635*2a598d0bSHerbert Xu 			if (!tmp)
636*2a598d0bSHerbert Xu 				return -EINVAL;
637*2a598d0bSHerbert Xu 			memcpy(buffer, tmp, n);
638*2a598d0bSHerbert Xu 			kfree(tmp);
639*2a598d0bSHerbert Xu 		}
640*2a598d0bSHerbert Xu 		*nwritten = n;
641*2a598d0bSHerbert Xu 		return 0;
642*2a598d0bSHerbert Xu 	} else if (format == GCRYMPI_FMT_PGP) {
643*2a598d0bSHerbert Xu 		unsigned int n = (nbits + 7)/8;
644*2a598d0bSHerbert Xu 
645*2a598d0bSHerbert Xu 		/* The PGP format can only handle unsigned integers.  */
646*2a598d0bSHerbert Xu 		if (negative)
647*2a598d0bSHerbert Xu 			return -EINVAL;
648*2a598d0bSHerbert Xu 
649*2a598d0bSHerbert Xu 		if (buffer && n+2 > len)
650*2a598d0bSHerbert Xu 			return -E2BIG;
651*2a598d0bSHerbert Xu 
652*2a598d0bSHerbert Xu 		if (buffer) {
653*2a598d0bSHerbert Xu 			unsigned char *tmp;
654*2a598d0bSHerbert Xu 			unsigned char *s = buffer;
655*2a598d0bSHerbert Xu 
656*2a598d0bSHerbert Xu 			s[0] = nbits >> 8;
657*2a598d0bSHerbert Xu 			s[1] = nbits;
658*2a598d0bSHerbert Xu 
659*2a598d0bSHerbert Xu 			tmp = mpi_get_buffer(a, &n, NULL);
660*2a598d0bSHerbert Xu 			if (!tmp)
661*2a598d0bSHerbert Xu 				return -EINVAL;
662*2a598d0bSHerbert Xu 			memcpy(s+2, tmp, n);
663*2a598d0bSHerbert Xu 			kfree(tmp);
664*2a598d0bSHerbert Xu 		}
665*2a598d0bSHerbert Xu 		*nwritten = n+2;
666*2a598d0bSHerbert Xu 		return 0;
667*2a598d0bSHerbert Xu 	} else if (format == GCRYMPI_FMT_SSH) {
668*2a598d0bSHerbert Xu 		unsigned char *tmp;
669*2a598d0bSHerbert Xu 		int extra = 0;
670*2a598d0bSHerbert Xu 		unsigned int n;
671*2a598d0bSHerbert Xu 
672*2a598d0bSHerbert Xu 		tmp = mpi_get_buffer(a, &n, NULL);
673*2a598d0bSHerbert Xu 		if (!tmp)
674*2a598d0bSHerbert Xu 			return -EINVAL;
675*2a598d0bSHerbert Xu 
676*2a598d0bSHerbert Xu 		if (negative) {
677*2a598d0bSHerbert Xu 			twocompl(tmp, n);
678*2a598d0bSHerbert Xu 			if (!(*tmp & 0x80)) {
679*2a598d0bSHerbert Xu 				/* Need to extend the sign.  */
680*2a598d0bSHerbert Xu 				n++;
681*2a598d0bSHerbert Xu 				extra = 2;
682*2a598d0bSHerbert Xu 			}
683*2a598d0bSHerbert Xu 		} else if (n && (*tmp & 0x80)) {
684*2a598d0bSHerbert Xu 			n++;
685*2a598d0bSHerbert Xu 			extra = 1;
686*2a598d0bSHerbert Xu 		}
687*2a598d0bSHerbert Xu 
688*2a598d0bSHerbert Xu 		if (buffer && n+4 > len) {
689*2a598d0bSHerbert Xu 			kfree(tmp);
690*2a598d0bSHerbert Xu 			return -E2BIG;
691*2a598d0bSHerbert Xu 		}
692*2a598d0bSHerbert Xu 
693*2a598d0bSHerbert Xu 		if (buffer) {
694*2a598d0bSHerbert Xu 			unsigned char *s = buffer;
695*2a598d0bSHerbert Xu 
696*2a598d0bSHerbert Xu 			*s++ = n >> 24;
697*2a598d0bSHerbert Xu 			*s++ = n >> 16;
698*2a598d0bSHerbert Xu 			*s++ = n >> 8;
699*2a598d0bSHerbert Xu 			*s++ = n;
700*2a598d0bSHerbert Xu 			if (extra == 1)
701*2a598d0bSHerbert Xu 				*s++ = 0;
702*2a598d0bSHerbert Xu 			else if (extra)
703*2a598d0bSHerbert Xu 				*s++ = 0xff;
704*2a598d0bSHerbert Xu 			memcpy(s, tmp, n-!!extra);
705*2a598d0bSHerbert Xu 		}
706*2a598d0bSHerbert Xu 		kfree(tmp);
707*2a598d0bSHerbert Xu 		*nwritten = 4+n;
708*2a598d0bSHerbert Xu 		return 0;
709*2a598d0bSHerbert Xu 	} else if (format == GCRYMPI_FMT_HEX) {
710*2a598d0bSHerbert Xu 		unsigned char *tmp;
711*2a598d0bSHerbert Xu 		int i;
712*2a598d0bSHerbert Xu 		int extra = 0;
713*2a598d0bSHerbert Xu 		unsigned int n = 0;
714*2a598d0bSHerbert Xu 
715*2a598d0bSHerbert Xu 		tmp = mpi_get_buffer(a, &n, NULL);
716*2a598d0bSHerbert Xu 		if (!tmp)
717*2a598d0bSHerbert Xu 			return -EINVAL;
718*2a598d0bSHerbert Xu 		if (!n || (*tmp & 0x80))
719*2a598d0bSHerbert Xu 			extra = 2;
720*2a598d0bSHerbert Xu 
721*2a598d0bSHerbert Xu 		if (buffer && 2*n + extra + negative + 1 > len) {
722*2a598d0bSHerbert Xu 			kfree(tmp);
723*2a598d0bSHerbert Xu 			return -E2BIG;
724*2a598d0bSHerbert Xu 		}
725*2a598d0bSHerbert Xu 		if (buffer) {
726*2a598d0bSHerbert Xu 			unsigned char *s = buffer;
727*2a598d0bSHerbert Xu 
728*2a598d0bSHerbert Xu 			if (negative)
729*2a598d0bSHerbert Xu 				*s++ = '-';
730*2a598d0bSHerbert Xu 			if (extra) {
731*2a598d0bSHerbert Xu 				*s++ = '0';
732*2a598d0bSHerbert Xu 				*s++ = '0';
733*2a598d0bSHerbert Xu 			}
734*2a598d0bSHerbert Xu 
735*2a598d0bSHerbert Xu 			for (i = 0; i < n; i++) {
736*2a598d0bSHerbert Xu 				unsigned int c = tmp[i];
737*2a598d0bSHerbert Xu 
738*2a598d0bSHerbert Xu 				*s++ = (c >> 4) < 10 ? '0'+(c>>4) : 'A'+(c>>4)-10;
739*2a598d0bSHerbert Xu 				c &= 15;
740*2a598d0bSHerbert Xu 				*s++ = c < 10 ? '0'+c : 'A'+c-10;
741*2a598d0bSHerbert Xu 			}
742*2a598d0bSHerbert Xu 			*s++ = 0;
743*2a598d0bSHerbert Xu 			*nwritten = s - buffer;
744*2a598d0bSHerbert Xu 		} else {
745*2a598d0bSHerbert Xu 			*nwritten = 2*n + extra + negative + 1;
746*2a598d0bSHerbert Xu 		}
747*2a598d0bSHerbert Xu 		kfree(tmp);
748*2a598d0bSHerbert Xu 		return 0;
749*2a598d0bSHerbert Xu 	} else
750*2a598d0bSHerbert Xu 		return -EINVAL;
751*2a598d0bSHerbert Xu }
752*2a598d0bSHerbert Xu EXPORT_SYMBOL_GPL(mpi_print);
753