• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* mpicoder.c  -  Coder for the external representation of MPIs
2  * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG 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 General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * 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 <linux/bitops.h>
22 #include <linux/count_zeros.h>
23 #include "mpi-internal.h"
24 
25 #define MAX_EXTERN_MPI_BITS 16384
26 
27 /**
28  * mpi_read_raw_data - Read a raw byte stream as a positive integer
29  * @xbuffer: The data to read
30  * @nbytes: The amount of data to read
31  */
mpi_read_raw_data(const void * xbuffer,size_t nbytes)32 MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes)
33 {
34 	const uint8_t *buffer = xbuffer;
35 	int i, j;
36 	unsigned nbits, nlimbs;
37 	mpi_limb_t a;
38 	MPI val = NULL;
39 
40 	while (nbytes > 0 && buffer[0] == 0) {
41 		buffer++;
42 		nbytes--;
43 	}
44 
45 	nbits = nbytes * 8;
46 	if (nbits > MAX_EXTERN_MPI_BITS) {
47 		pr_info("MPI: mpi too large (%u bits)\n", nbits);
48 		return NULL;
49 	}
50 	if (nbytes > 0)
51 		nbits -= count_leading_zeros(buffer[0]);
52 	else
53 		nbits = 0;
54 
55 	nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB);
56 	val = mpi_alloc(nlimbs);
57 	if (!val)
58 		return NULL;
59 	val->nbits = nbits;
60 	val->sign = 0;
61 	val->nlimbs = nlimbs;
62 
63 	if (nbytes > 0) {
64 		i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
65 		i %= BYTES_PER_MPI_LIMB;
66 		for (j = nlimbs; j > 0; j--) {
67 			a = 0;
68 			for (; i < BYTES_PER_MPI_LIMB; i++) {
69 				a <<= 8;
70 				a |= *buffer++;
71 			}
72 			i = 0;
73 			val->d[j - 1] = a;
74 		}
75 	}
76 	return val;
77 }
78 EXPORT_SYMBOL_GPL(mpi_read_raw_data);
79 
mpi_read_from_buffer(const void * xbuffer,unsigned * ret_nread)80 MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)
81 {
82 	const uint8_t *buffer = xbuffer;
83 	int i, j;
84 	unsigned nbits, nbytes, nlimbs, nread = 0;
85 	mpi_limb_t a;
86 	MPI val = NULL;
87 
88 	if (*ret_nread < 2)
89 		goto leave;
90 	nbits = buffer[0] << 8 | buffer[1];
91 
92 	if (nbits > MAX_EXTERN_MPI_BITS) {
93 		pr_info("MPI: mpi too large (%u bits)\n", nbits);
94 		goto leave;
95 	}
96 	buffer += 2;
97 	nread = 2;
98 
99 	nbytes = DIV_ROUND_UP(nbits, 8);
100 	nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB);
101 	val = mpi_alloc(nlimbs);
102 	if (!val)
103 		return NULL;
104 	i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
105 	i %= BYTES_PER_MPI_LIMB;
106 	val->nbits = nbits;
107 	j = val->nlimbs = nlimbs;
108 	val->sign = 0;
109 	for (; j > 0; j--) {
110 		a = 0;
111 		for (; i < BYTES_PER_MPI_LIMB; i++) {
112 			if (++nread > *ret_nread) {
113 				printk
114 				    ("MPI: mpi larger than buffer nread=%d ret_nread=%d\n",
115 				     nread, *ret_nread);
116 				goto leave;
117 			}
118 			a <<= 8;
119 			a |= *buffer++;
120 		}
121 		i = 0;
122 		val->d[j - 1] = a;
123 	}
124 
125 leave:
126 	*ret_nread = nread;
127 	return val;
128 }
129 EXPORT_SYMBOL_GPL(mpi_read_from_buffer);
130 
count_lzeros(MPI a)131 static int count_lzeros(MPI a)
132 {
133 	mpi_limb_t alimb;
134 	int i, lzeros = 0;
135 
136 	for (i = a->nlimbs - 1; i >= 0; i--) {
137 		alimb = a->d[i];
138 		if (alimb == 0) {
139 			lzeros += sizeof(mpi_limb_t);
140 		} else {
141 			lzeros += count_leading_zeros(alimb) / 8;
142 			break;
143 		}
144 	}
145 	return lzeros;
146 }
147 
148 /**
149  * mpi_read_buffer() - read MPI to a bufer provided by user (msb first)
150  *
151  * @a:		a multi precision integer
152  * @buf:	bufer to which the output will be written to. Needs to be at
153  *		leaset mpi_get_size(a) long.
154  * @buf_len:	size of the buf.
155  * @nbytes:	receives the actual length of the data written.
156  * @sign:	if not NULL, it will be set to the sign of a.
157  *
158  * Return:	0 on success or error code in case of error
159  */
mpi_read_buffer(MPI a,uint8_t * buf,unsigned buf_len,unsigned * nbytes,int * sign)160 int mpi_read_buffer(MPI a, uint8_t *buf, unsigned buf_len, unsigned *nbytes,
161 		    int *sign)
162 {
163 	uint8_t *p;
164 	mpi_limb_t alimb;
165 	unsigned int n = mpi_get_size(a);
166 	int i, lzeros;
167 
168 	if (buf_len < n || !buf || !nbytes)
169 		return -EINVAL;
170 
171 	if (sign)
172 		*sign = a->sign;
173 
174 	lzeros = count_lzeros(a);
175 
176 	p = buf;
177 	*nbytes = n - lzeros;
178 
179 	for (i = a->nlimbs - 1; i >= 0; i--) {
180 		alimb = a->d[i];
181 #if BYTES_PER_MPI_LIMB == 4
182 		*p++ = alimb >> 24;
183 		*p++ = alimb >> 16;
184 		*p++ = alimb >> 8;
185 		*p++ = alimb;
186 #elif BYTES_PER_MPI_LIMB == 8
187 		*p++ = alimb >> 56;
188 		*p++ = alimb >> 48;
189 		*p++ = alimb >> 40;
190 		*p++ = alimb >> 32;
191 		*p++ = alimb >> 24;
192 		*p++ = alimb >> 16;
193 		*p++ = alimb >> 8;
194 		*p++ = alimb;
195 #else
196 #error please implement for this limb size.
197 #endif
198 
199 		if (lzeros > 0) {
200 			if (lzeros >= sizeof(alimb)) {
201 				p -= sizeof(alimb);
202 			} else {
203 				mpi_limb_t *limb1 = (void *)p - sizeof(alimb);
204 				mpi_limb_t *limb2 = (void *)p - sizeof(alimb)
205 							+ lzeros;
206 				*limb1 = *limb2;
207 				p -= lzeros;
208 			}
209 			lzeros -= sizeof(alimb);
210 		}
211 	}
212 	return 0;
213 }
214 EXPORT_SYMBOL_GPL(mpi_read_buffer);
215 
216 /*
217  * mpi_get_buffer() - Returns an allocated buffer with the MPI (msb first).
218  * Caller must free the return string.
219  * This function does return a 0 byte buffer with nbytes set to zero if the
220  * value of A is zero.
221  *
222  * @a:		a multi precision integer.
223  * @nbytes:	receives the length of this buffer.
224  * @sign:	if not NULL, it will be set to the sign of the a.
225  *
226  * Return:	Pointer to MPI buffer or NULL on error
227  */
mpi_get_buffer(MPI a,unsigned * nbytes,int * sign)228 void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign)
229 {
230 	uint8_t *buf;
231 	unsigned int n;
232 	int ret;
233 
234 	if (!nbytes)
235 		return NULL;
236 
237 	n = mpi_get_size(a);
238 
239 	if (!n)
240 		n++;
241 
242 	buf = kmalloc(n, GFP_KERNEL);
243 
244 	if (!buf)
245 		return NULL;
246 
247 	ret = mpi_read_buffer(a, buf, n, nbytes, sign);
248 
249 	if (ret) {
250 		kfree(buf);
251 		return NULL;
252 	}
253 	return buf;
254 }
255 EXPORT_SYMBOL_GPL(mpi_get_buffer);
256 
257 /****************
258  * Use BUFFER to update MPI.
259  */
mpi_set_buffer(MPI a,const void * xbuffer,unsigned nbytes,int sign)260 int mpi_set_buffer(MPI a, const void *xbuffer, unsigned nbytes, int sign)
261 {
262 	const uint8_t *buffer = xbuffer, *p;
263 	mpi_limb_t alimb;
264 	int nlimbs;
265 	int i;
266 
267 	nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB);
268 	if (RESIZE_IF_NEEDED(a, nlimbs) < 0)
269 		return -ENOMEM;
270 	a->sign = sign;
271 
272 	for (i = 0, p = buffer + nbytes - 1; p >= buffer + BYTES_PER_MPI_LIMB;) {
273 #if BYTES_PER_MPI_LIMB == 4
274 		alimb = (mpi_limb_t) *p--;
275 		alimb |= (mpi_limb_t) *p-- << 8;
276 		alimb |= (mpi_limb_t) *p-- << 16;
277 		alimb |= (mpi_limb_t) *p-- << 24;
278 #elif BYTES_PER_MPI_LIMB == 8
279 		alimb = (mpi_limb_t) *p--;
280 		alimb |= (mpi_limb_t) *p-- << 8;
281 		alimb |= (mpi_limb_t) *p-- << 16;
282 		alimb |= (mpi_limb_t) *p-- << 24;
283 		alimb |= (mpi_limb_t) *p-- << 32;
284 		alimb |= (mpi_limb_t) *p-- << 40;
285 		alimb |= (mpi_limb_t) *p-- << 48;
286 		alimb |= (mpi_limb_t) *p-- << 56;
287 #else
288 #error please implement for this limb size.
289 #endif
290 		a->d[i++] = alimb;
291 	}
292 	if (p >= buffer) {
293 #if BYTES_PER_MPI_LIMB == 4
294 		alimb = *p--;
295 		if (p >= buffer)
296 			alimb |= (mpi_limb_t) *p-- << 8;
297 		if (p >= buffer)
298 			alimb |= (mpi_limb_t) *p-- << 16;
299 		if (p >= buffer)
300 			alimb |= (mpi_limb_t) *p-- << 24;
301 #elif BYTES_PER_MPI_LIMB == 8
302 		alimb = (mpi_limb_t) *p--;
303 		if (p >= buffer)
304 			alimb |= (mpi_limb_t) *p-- << 8;
305 		if (p >= buffer)
306 			alimb |= (mpi_limb_t) *p-- << 16;
307 		if (p >= buffer)
308 			alimb |= (mpi_limb_t) *p-- << 24;
309 		if (p >= buffer)
310 			alimb |= (mpi_limb_t) *p-- << 32;
311 		if (p >= buffer)
312 			alimb |= (mpi_limb_t) *p-- << 40;
313 		if (p >= buffer)
314 			alimb |= (mpi_limb_t) *p-- << 48;
315 		if (p >= buffer)
316 			alimb |= (mpi_limb_t) *p-- << 56;
317 #else
318 #error please implement for this limb size.
319 #endif
320 		a->d[i++] = alimb;
321 	}
322 	a->nlimbs = i;
323 
324 	if (i != nlimbs) {
325 		pr_emerg("MPI: mpi_set_buffer: Assertion failed (%d != %d)", i,
326 		       nlimbs);
327 		BUG();
328 	}
329 	return 0;
330 }
331 EXPORT_SYMBOL_GPL(mpi_set_buffer);
332 
333 /**
334  * mpi_write_to_sgl() - Funnction exports MPI to an sgl (msb first)
335  *
336  * This function works in the same way as the mpi_read_buffer, but it
337  * takes an sgl instead of u8 * buf.
338  *
339  * @a:		a multi precision integer
340  * @sgl:	scatterlist to write to. Needs to be at least
341  *		mpi_get_size(a) long.
342  * @nbytes:	in/out param - it has the be set to the maximum number of
343  *		bytes that can be written to sgl. This has to be at least
344  *		the size of the integer a. On return it receives the actual
345  *		length of the data written.
346  * @sign:	if not NULL, it will be set to the sign of a.
347  *
348  * Return:	0 on success or error code in case of error
349  */
mpi_write_to_sgl(MPI a,struct scatterlist * sgl,unsigned * nbytes,int * sign)350 int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned *nbytes,
351 		     int *sign)
352 {
353 	u8 *p, *p2;
354 	mpi_limb_t alimb, alimb2;
355 	unsigned int n = mpi_get_size(a);
356 	int i, x, y = 0, lzeros, buf_len;
357 
358 	if (!nbytes || *nbytes < n)
359 		return -EINVAL;
360 
361 	if (sign)
362 		*sign = a->sign;
363 
364 	lzeros = count_lzeros(a);
365 
366 	*nbytes = n - lzeros;
367 	buf_len = sgl->length;
368 	p2 = sg_virt(sgl);
369 
370 	for (i = a->nlimbs - 1 - lzeros / BYTES_PER_MPI_LIMB,
371 			lzeros %= BYTES_PER_MPI_LIMB;
372 		i >= 0; i--) {
373 		alimb = a->d[i];
374 		p = (u8 *)&alimb2;
375 #if BYTES_PER_MPI_LIMB == 4
376 		*p++ = alimb >> 24;
377 		*p++ = alimb >> 16;
378 		*p++ = alimb >> 8;
379 		*p++ = alimb;
380 #elif BYTES_PER_MPI_LIMB == 8
381 		*p++ = alimb >> 56;
382 		*p++ = alimb >> 48;
383 		*p++ = alimb >> 40;
384 		*p++ = alimb >> 32;
385 		*p++ = alimb >> 24;
386 		*p++ = alimb >> 16;
387 		*p++ = alimb >> 8;
388 		*p++ = alimb;
389 #else
390 #error please implement for this limb size.
391 #endif
392 		if (lzeros > 0) {
393 			mpi_limb_t *limb1 = (void *)p - sizeof(alimb);
394 			mpi_limb_t *limb2 = (void *)p - sizeof(alimb)
395 				+ lzeros;
396 			*limb1 = *limb2;
397 			p -= lzeros;
398 			y = lzeros;
399 			lzeros -= sizeof(alimb);
400 		}
401 
402 		p = p - (sizeof(alimb) - y);
403 
404 		for (x = 0; x < sizeof(alimb) - y; x++) {
405 			if (!buf_len) {
406 				sgl = sg_next(sgl);
407 				if (!sgl)
408 					return -EINVAL;
409 				buf_len = sgl->length;
410 				p2 = sg_virt(sgl);
411 			}
412 			*p2++ = *p++;
413 			buf_len--;
414 		}
415 		y = 0;
416 	}
417 	return 0;
418 }
419 EXPORT_SYMBOL_GPL(mpi_write_to_sgl);
420 
421 /*
422  * mpi_read_raw_from_sgl() - Function allocates an MPI and populates it with
423  *			     data from the sgl
424  *
425  * This function works in the same way as the mpi_read_raw_data, but it
426  * takes an sgl instead of void * buffer. i.e. it allocates
427  * a new MPI and reads the content of the sgl to the MPI.
428  *
429  * @sgl:	scatterlist to read from
430  * @len:	number of bytes to read
431  *
432  * Return:	Pointer to a new MPI or NULL on error
433  */
mpi_read_raw_from_sgl(struct scatterlist * sgl,unsigned int len)434 MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int len)
435 {
436 	struct scatterlist *sg;
437 	int x, i, j, z, lzeros, ents;
438 	unsigned int nbits, nlimbs, nbytes;
439 	mpi_limb_t a;
440 	MPI val = NULL;
441 
442 	lzeros = 0;
443 	ents = sg_nents(sgl);
444 
445 	for_each_sg(sgl, sg, ents, i) {
446 		const u8 *buff = sg_virt(sg);
447 		int len = sg->length;
448 
449 		while (len && !*buff) {
450 			lzeros++;
451 			len--;
452 			buff++;
453 		}
454 
455 		if (len && *buff)
456 			break;
457 
458 		ents--;
459 		lzeros = 0;
460 	}
461 
462 	sgl = sg;
463 
464 	if (!ents)
465 		nbytes = 0;
466 	else
467 		nbytes = len - lzeros;
468 
469 	nbits = nbytes * 8;
470 	if (nbits > MAX_EXTERN_MPI_BITS) {
471 		pr_info("MPI: mpi too large (%u bits)\n", nbits);
472 		return NULL;
473 	}
474 
475 	if (nbytes > 0)
476 		nbits -= count_leading_zeros(*(u8 *)(sg_virt(sgl) + lzeros));
477 	else
478 		nbits = 0;
479 
480 	nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB);
481 	val = mpi_alloc(nlimbs);
482 	if (!val)
483 		return NULL;
484 
485 	val->nbits = nbits;
486 	val->sign = 0;
487 	val->nlimbs = nlimbs;
488 
489 	if (nbytes == 0)
490 		return val;
491 
492 	j = nlimbs - 1;
493 	a = 0;
494 	z = 0;
495 	x = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
496 	x %= BYTES_PER_MPI_LIMB;
497 
498 	for_each_sg(sgl, sg, ents, i) {
499 		const u8 *buffer = sg_virt(sg) + lzeros;
500 		int len = sg->length - lzeros;
501 		int buf_shift = x;
502 
503 		if  (sg_is_last(sg) && (len % BYTES_PER_MPI_LIMB))
504 			len += BYTES_PER_MPI_LIMB - (len % BYTES_PER_MPI_LIMB);
505 
506 		for (; x < len + buf_shift; x++) {
507 			a <<= 8;
508 			a |= *buffer++;
509 			if (((z + x + 1) % BYTES_PER_MPI_LIMB) == 0) {
510 				val->d[j--] = a;
511 				a = 0;
512 			}
513 		}
514 		z += x;
515 		x = 0;
516 		lzeros = 0;
517 	}
518 	return val;
519 }
520 EXPORT_SYMBOL_GPL(mpi_read_raw_from_sgl);
521