41663337e8b42dcea82518641bf376fe61ca12ff
[strongswan.git] / src / pluto / mp_defs.c
1 /* some multiprecision utilities
2 * Copyright (C) 1998-2001 D. Hugh Redelmeier.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 */
14
15 #include <freeswan.h>
16
17 #include <utils.h>
18 #include <asn1/asn1.h>
19
20 #include "constants.h"
21 #include "defs.h"
22 #include "mp_defs.h"
23 #include "log.h"
24
25 /* Convert MP_INT to network form (binary octets, big-endian).
26 * We do the malloc; caller must eventually do free.
27 */
28 chunk_t
29 mpz_to_n(const MP_INT *mp, size_t bytes)
30 {
31 chunk_t r;
32 MP_INT temp1, temp2;
33 int i;
34
35 r.len = bytes;
36 r.ptr = malloc(r.len);
37
38 mpz_init(&temp1);
39 mpz_init(&temp2);
40
41 mpz_set(&temp1, mp);
42
43 for (i = r.len-1; i >= 0; i--)
44 {
45 r.ptr[i] = mpz_mdivmod_ui(&temp2, NULL, &temp1, 1 << BITS_PER_BYTE);
46 mpz_set(&temp1, &temp2);
47 }
48
49 passert(mpz_sgn(&temp1) == 0); /* we must have done all the bits */
50 mpz_clear(&temp1);
51 mpz_clear(&temp2);
52
53 return r;
54 }
55
56 /* Convert network form (binary bytes, big-endian) to MP_INT.
57 * The *mp must not be previously mpz_inited.
58 */
59 void
60 n_to_mpz(MP_INT *mp, const u_char *nbytes, size_t nlen)
61 {
62 size_t i;
63
64 mpz_init_set_ui(mp, 0);
65
66 for (i = 0; i != nlen; i++)
67 {
68 mpz_mul_ui(mp, mp, 1 << BITS_PER_BYTE);
69 mpz_add_ui(mp, mp, nbytes[i]);
70 }
71 }
72
73 /*
74 * convert a MP integer into a DER coded ASN.1 object
75 */
76 chunk_t
77 asn1_integer_from_mpz(const mpz_t value)
78 {
79 size_t bits = mpz_sizeinbase(value, 2); /* size in bits */
80 size_t size = 1 + bits / BITS_PER_BYTE; /* size in bytes */
81 chunk_t n = mpz_to_n(value, size);
82
83 return asn1_wrap(ASN1_INTEGER, "m", n);
84 }
85