1 /* borrowed from isakmpd-20030718 (-; */
3 /* $OpenBSD: math_group.c,v 1.18 2003/06/03 14:28:16 ho Exp $ */
4 /* $EOM: math_group.c,v 1.25 2000/04/07 19:53:26 niklas Exp $ */
7 * Copyright (c) 1998 Niels Provos. All rights reserved.
8 * Copyright (c) 1999, 2000 Niklas Hallqvist. All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * This code was written under funding by Ericsson Radio Systems.
36 #include <sys/param.h>
39 #include <netinet/in.h>
43 #include "math_group.h"
45 /* We do not want to export these definitions. */
46 static void modp_free(struct group
*);
47 static struct group
*modp_clone(struct group
*, struct group
*);
48 static void modp_init(struct group
*);
50 static int modp_getlen(struct group
*);
51 static void modp_getraw(struct group
*, gcry_mpi_t
, unsigned char *);
52 static int modp_setraw(struct group
*, gcry_mpi_t
, unsigned char *, int);
53 static int modp_setrandom(struct group
*, gcry_mpi_t
);
54 static int modp_operation(struct group
*, gcry_mpi_t
, gcry_mpi_t
, gcry_mpi_t
);
57 * This module provides access to the operations on the specified group
58 * and is absolutly free of any cryptographic devices. This is math :-).
61 /* Describe preconfigured MODP groups */
64 * The Generalized Number Field Sieve has an asymptotic running time
65 * of: O(exp(1.9223 * (ln q)^(1/3) (ln ln q)^(2/3))), where q is the
66 * group order, e.g. q = 2**768.
69 static const struct modp_dscr oakley_modp
[] = {
71 OAKLEY_GRP_1
, 72, /* This group is insecure, only sufficient for DES */
72 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
73 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
74 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
75 "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF",
79 OAKLEY_GRP_2
, 82, /* This group is a bit better */
80 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
81 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
82 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
83 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
84 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381"
89 OAKLEY_GRP_5
, 102, /* This group is yet a bit better, but non-standard */
90 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
91 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
92 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
93 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
94 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
95 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
96 "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
97 "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF",
102 /* XXX I want to get rid of the casting here. */
103 static struct group groups
[] = {
105 MODP
, OAKLEY_GRP_1
, 0, NULL
, &oakley_modp
[0], NULL
, NULL
, NULL
, NULL
, NULL
,
106 (int (*)(struct group
*))modp_getlen
,
107 (void (*)(struct group
*, void *, unsigned char *))modp_getraw
,
108 (int (*)(struct group
*, void *, unsigned char *, int))modp_setraw
,
109 (int (*)(struct group
*, void *))modp_setrandom
,
110 (int (*)(struct group
*, void *, void *, void *))modp_operation
113 MODP
, OAKLEY_GRP_2
, 0, NULL
, &oakley_modp
[1], NULL
, NULL
, NULL
, NULL
, NULL
,
114 (int (*)(struct group
*))modp_getlen
,
115 (void (*)(struct group
*, void *, unsigned char *))modp_getraw
,
116 (int (*)(struct group
*, void *, unsigned char *, int))modp_setraw
,
117 (int (*)(struct group
*, void *))modp_setrandom
,
118 (int (*)(struct group
*, void *, void *, void *))modp_operation
121 MODP
, OAKLEY_GRP_5
, 0, NULL
, &oakley_modp
[2], NULL
, NULL
, NULL
, NULL
, NULL
,
122 (int (*)(struct group
*))modp_getlen
,
123 (void (*)(struct group
*, void *, unsigned char *))modp_getraw
,
124 (int (*)(struct group
*, void *, unsigned char *, int))modp_setraw
,
125 (int (*)(struct group
*, void *))modp_setrandom
,
126 (int (*)(struct group
*, void *, void *, void *))modp_operation
131 * Initialize the group structure for later use,
132 * this is done by converting the values given in the describtion
133 * and converting them to their native representation.
135 void group_init(void)
139 for (i
= sizeof(groups
) / sizeof(groups
[0]) - 1; i
>= 0; i
--) {
140 assert(groups
[i
].type
== MODP
);
141 modp_init(&groups
[i
]); /* Initialize an over GF(p) */
145 struct group
*group_get(int id
)
147 struct group
*new, *clone
;
150 assert(id
<= (int)(sizeof(groups
) / sizeof(groups
[0])));
152 clone
= &groups
[id
- 1];
154 new = malloc(sizeof *new);
157 assert(clone
->type
== MODP
);
158 new = modp_clone(new, clone
);
162 void group_free(struct group
*grp
)
164 assert(grp
->type
== MODP
);
169 static struct group
*modp_clone(struct group
*new, struct group
*clone
)
171 struct modp_group
*new_grp
, *clone_grp
= clone
->group
;
173 new_grp
= malloc(sizeof *new_grp
);
176 memcpy(new, clone
, sizeof(struct group
));
178 new->group
= new_grp
;
179 new_grp
->p
= gcry_mpi_copy(clone_grp
->p
);
180 new_grp
->gen
= gcry_mpi_copy(clone_grp
->gen
);
182 new_grp
->a
= gcry_mpi_new(clone
->bits
);
183 new_grp
->b
= gcry_mpi_new(clone
->bits
);
184 new_grp
->c
= gcry_mpi_new(clone
->bits
);
186 new->gen
= new_grp
->gen
;
194 static void modp_free(struct group
*old
)
196 struct modp_group
*grp
= old
->group
;
198 gcry_mpi_release(grp
->p
);
199 gcry_mpi_release(grp
->gen
);
200 gcry_mpi_release(grp
->a
);
201 gcry_mpi_release(grp
->b
);
202 gcry_mpi_release(grp
->c
);
207 static void modp_init(struct group
*group
)
209 const struct modp_dscr
*dscr
= group
->group_dscr
;
210 struct modp_group
*grp
;
212 grp
= malloc(sizeof *grp
);
215 group
->bits
= dscr
->bits
;
217 gcry_mpi_scan(&grp
->p
, GCRYMPI_FMT_HEX
, (const unsigned char*)dscr
->prime
, 0, NULL
);
218 gcry_mpi_scan(&grp
->gen
, GCRYMPI_FMT_HEX
, (const unsigned char *)dscr
->gen
, 0, NULL
);
220 grp
->a
= gcry_mpi_new(group
->bits
);
221 grp
->b
= gcry_mpi_new(group
->bits
);
222 grp
->c
= gcry_mpi_new(group
->bits
);
224 group
->gen
= grp
->gen
;
232 static int modp_getlen(struct group
*group
)
234 struct modp_group
*grp
= (struct modp_group
*)group
->group
;
236 return (gcry_mpi_get_nbits(grp
->p
) + 7) / 8;
239 static void modp_getraw(struct group
*grp
, gcry_mpi_t v
, unsigned char *d
)
245 l
= grp
->getlen(grp
);
246 ret
= gcry_mpi_aprint(GCRYMPI_FMT_STD
, &tmp
, &l2
, v
);
247 memcpy(d
, tmp
+ (l2
- l
), l
);
252 gcry_mpi_aprint(GCRYMPI_FMT_HEX
, (void **)&p
, NULL
, v
);
253 printf("export %d - %d(%d):\n%s\n", l
, l2
, ret
, p
);
259 static int modp_setraw(struct group
*grp
, gcry_mpi_t d
, unsigned char *s
, int l
)
263 grp
= NULL
; /* unused */
265 gcry_mpi_set_ui(d
, 0);
266 for (i
= 0; i
< l
; i
++) {
267 gcry_mpi_mul_2exp(d
, d
, 8);
268 gcry_mpi_add_ui(d
, d
, s
[i
]);
273 gcry_mpi_aprint(GCRYMPI_FMT_HEX
, (void **)&p
, NULL
, d
);
274 printf("import %d:\n%s\n", l
, p
);
281 static int modp_setrandom(struct group
*grp
, gcry_mpi_t d
)
283 int i
, l
= grp
->getlen(grp
);
286 gcry_mpi_set_ui(d
, 0);
288 for (i
= 0; i
< l
; i
++) {
290 gcry_randomize((unsigned char *)&tmp
, sizeof(tmp
), GCRY_STRONG_RANDOM
);
292 gcry_mpi_mul_2exp(d
, d
, 8);
293 gcry_mpi_add_ui(d
, d
, tmp
& 0xFF);
299 static int modp_operation(struct group
*group
, gcry_mpi_t d
, gcry_mpi_t a
, gcry_mpi_t e
)
301 struct modp_group
*grp
= (struct modp_group
*)group
->group
;
303 gcry_mpi_powm(d
, a
, e
, grp
->p
);