Added SILC Server library.
[silc.git] / lib / silcske / groups.c
1 /*
2
3   groups.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2000 - 2001 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12   
13   This program 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 General Public License for more details.
17
18 */
19 /* $Id$ */
20
21 #include "silc.h"
22 #include "groups_internal.h"
23
24 /* Fixed and public Diffie Hellman Groups defined by the SKE
25    protocol. These are equivalent to the OAKLEY Key Determination
26    protocol groups (taken from RFC 2412). */
27 const struct SilcSKEDiffieHellmanGroupDefStruct silc_ske_groups[] = 
28 {
29   /* 1024 bits modulus (Mandatory group) */
30   { 1, "diffie-hellman-group1",
31
32     "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
33     "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
34     "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
35     "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
36     "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381"
37     "FFFFFFFFFFFFFFFF",
38
39     "7FFFFFFFFFFFFFFFE487ED5110B4611A62633145C06E0E68"
40     "948127044533E63A0105DF531D89CD9128A5043CC71A026E"
41     "F7CA8CD9E69D218D98158536F92F8A1BA7F09AB6B6A8E122"
42     "F242DABB312F3F637A262174D31BF6B585FFAE5B7A035BF6"
43     "F71C35FDAD44CFD2D74F9208BE258FF324943328F67329C0"
44     "FFFFFFFFFFFFFFFF",
45     "2" },
46
47   /* 1536 bits modulus (Optional group) */
48   { 2, "diffie-hellman-group2",
49
50     "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
51     "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
52     "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
53     "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
54     "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
55     "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
56     "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
57     "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF",
58
59     "7FFFFFFFFFFFFFFFE487ED5110B4611A62633145C06E0E68"
60     "948127044533E63A0105DF531D89CD9128A5043CC71A026E"
61     "F7CA8CD9E69D218D98158536F92F8A1BA7F09AB6B6A8E122"
62     "F242DABB312F3F637A262174D31BF6B585FFAE5B7A035BF6"
63     "F71C35FDAD44CFD2D74F9208BE258FF324943328F6722D9E"
64     "E1003E5C50B1DF82CC6D241B0E2AE9CD348B1FD47E9267AF"
65     "C1B2AE91EE51D6CB0E3179AB1042A95DCF6A9483B84B4B36"
66     "B3861AA7255E4C0278BA36046511B993FFFFFFFFFFFFFFFF",
67     "2" },
68
69   { 0, NULL, NULL, NULL }
70 };
71
72 /* Returns Diffie Hellman group by group number */
73
74 SilcSKEStatus silc_ske_group_get_by_number(int number,
75                                            SilcSKEDiffieHellmanGroup *ret)
76 {
77   int i;
78   SilcSKEDiffieHellmanGroup group;
79
80   for (i = 0; silc_ske_groups[i].name; i++) {
81     if (silc_ske_groups[i].number == number)
82       break;
83   }
84
85   if (silc_ske_groups[i].name == NULL) {
86     SILC_LOG_ERROR(("Unsupported Diffie-Hellman group number %d", number));
87     return SILC_SKE_STATUS_UNKNOWN_GROUP;
88   }
89
90   /* Return the group */
91   if (ret) {
92     group = silc_calloc(1, sizeof(*group));
93     group->number = number;
94     group->name = silc_ske_groups[i].name;
95     silc_mp_init(&group->group);
96     silc_mp_init(&group->group_order);
97     silc_mp_init(&group->generator);
98     silc_mp_set_str(&group->group, silc_ske_groups[i].group, 16);
99     silc_mp_set_str(&group->group_order, silc_ske_groups[i].group_order, 16);
100     silc_mp_set_str(&group->generator, silc_ske_groups[i].generator, 16);
101     
102     *ret = group;
103   }
104
105   return SILC_SKE_STATUS_OK;
106 }
107
108 /* Returns Diffie Hellman group by name */
109
110 SilcSKEStatus silc_ske_group_get_by_name(const char *name,
111                                          SilcSKEDiffieHellmanGroup *ret)
112 {
113   int i;
114   SilcSKEDiffieHellmanGroup group;
115
116   for (i = 0; silc_ske_groups[i].name; i++) {
117     if (!strcmp(silc_ske_groups[i].name, name))
118       break;
119   }
120
121   if (silc_ske_groups[i].name == NULL) {
122     SILC_LOG_ERROR(("Unsupported Diffie-Hellman group `%s'", name));
123     return SILC_SKE_STATUS_UNKNOWN_GROUP;
124   }
125
126   /* Return the group */
127   if (ret) {
128     group = silc_calloc(1, sizeof(*group));
129     group->number = silc_ske_groups[i].number;
130     group->name = silc_ske_groups[i].name;
131     silc_mp_init(&group->group);
132     silc_mp_init(&group->group_order);
133     silc_mp_init(&group->generator);
134     silc_mp_set_str(&group->group, silc_ske_groups[i].group, 16);
135     silc_mp_set_str(&group->group_order, silc_ske_groups[i].group_order, 16);
136     silc_mp_set_str(&group->generator, silc_ske_groups[i].generator, 16);
137     
138     *ret = group;
139   }
140
141   return SILC_SKE_STATUS_OK;
142 }
143
144 /* Free group */
145
146 void silc_ske_group_free(SilcSKEDiffieHellmanGroup group)
147 {
148   silc_mp_uninit(&group->group);
149   silc_mp_uninit(&group->group_order);
150   silc_mp_uninit(&group->generator);
151   silc_free(group);
152 }
153
154 /* Returns comma separated list of supported groups */
155
156 char *silc_ske_get_supported_groups()
157 {
158   char *list = NULL;
159   int i, len;
160
161   len = 0;
162   for (i = 0; silc_ske_groups[i].name; i++) {
163     len += strlen(silc_ske_groups[i].name);
164     list = silc_realloc(list, len + 1);
165
166     memcpy(list + (len - strlen(silc_ske_groups[i].name)), 
167            silc_ske_groups[i].name, strlen(silc_ske_groups[i].name));
168     memcpy(list + len, ",", 1);
169     len++;
170   }
171
172   list[len - 1] = 0;
173
174   return list;
175 }
176
177 /* Returns the number of the `group'. */
178
179 int silc_ske_group_get_number(SilcSKEDiffieHellmanGroup group)
180 {
181   return group->number;
182 }
183
184 /* Returns the name of the `group'. */
185
186 const char *silc_ske_group_get_name(SilcSKEDiffieHellmanGroup group)
187 {
188   return group->name;
189 }