Initial revision
[silc.git] / lib / silccrypt / silcpkcs.c
1 /*
2
3   silcpkcs.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2000 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; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20
21 #include "silcincludes.h"
22
23 #include "rsa.h"
24
25 /* List of all PKCS's in SILC. PKCS's don't support SIM's thus
26    only static declarations are possible. XXX: I hope this to change
27    real soon. */
28 SilcPKCSObject silc_pkcs_list[] =
29 {
30   { "rsa", &silc_rsa_data_context, 
31     silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key,
32     silc_rsa_get_private_key, silc_rsa_set_public_key,
33     silc_rsa_set_private_key, silc_rsa_context_len,
34     silc_rsa_data_context_len, silc_rsa_set_arg,
35     silc_rsa_encrypt, silc_rsa_decrypt,
36     silc_rsa_sign, silc_rsa_verify },
37
38   { NULL, NULL, NULL, NULL, NULL,
39     NULL, NULL, NULL, NULL, NULL, NULL }
40 };
41
42 /* Allocates a new SilcPKCS object. The new allocated object is returned
43    to the 'new_pkcs' argument. This function also initializes the data
44    context structure. Function returns 1 on success and 0 on error.
45
46 */
47 int silc_pkcs_alloc(const unsigned char *name, SilcPKCS *new_pkcs)
48 {
49   int i;
50
51   SILC_LOG_DEBUG(("Allocating new PKCS object"));
52
53   for (i = 0; silc_pkcs_list[i].name; i++) {
54     if (!strcmp(silc_pkcs_list[i].name, name))
55       break;
56   }
57
58   if (silc_pkcs_list[i].name == NULL)
59     return FALSE;
60
61   *new_pkcs = silc_calloc(1, sizeof(**new_pkcs));
62   if (*new_pkcs == NULL) {
63     SILC_LOG_ERROR(("Could not allocate new PKCS object"));
64     return FALSE;
65   }
66
67   /* Set the pointers */
68   (*new_pkcs)->pkcs = &silc_pkcs_list[i];
69   (*new_pkcs)->pkcs->data_context = 
70     silc_calloc(1, (*new_pkcs)->pkcs->data_context_len());
71   (*new_pkcs)->context = silc_calloc(1, (*new_pkcs)->pkcs->context_len());
72   (*new_pkcs)->get_key_len = silc_pkcs_get_key_len;
73
74   return TRUE;
75 }
76
77 /* Free's the PKCS object */
78
79 void silc_pkcs_free(SilcPKCS pkcs)
80 {
81   if (pkcs)
82     silc_free(pkcs->context);
83 }
84
85 /* Return TRUE if PKCS algorithm `name' is supported. */
86
87 int silc_pkcs_is_supported(const unsigned char *name)
88 {
89   int i;
90
91   for (i = 0; silc_pkcs_list[i].name; i++) {
92     if (!strcmp(silc_pkcs_list[i].name, name))
93       return TRUE;
94   }
95
96   return FALSE;
97 }
98
99 /* Returns comma separated list of supported PKCS algorithms */
100
101 char *silc_pkcs_get_supported()
102 {
103   char *list = NULL;
104   int i, len;
105
106   len = 0;
107   for (i = 0; silc_pkcs_list[i].name; i++) {
108     len += strlen(silc_pkcs_list[i].name);
109     list = silc_realloc(list, len + 1);
110
111     memcpy(list + (len - strlen(silc_pkcs_list[i].name)), 
112            silc_pkcs_list[i].name, strlen(silc_pkcs_list[i].name));
113     memcpy(list + len, ",", 1);
114     len++;
115   }
116
117   list[len - 1] = 0;
118
119   return list;
120 }
121
122 /* Returns the length of the key */
123
124 unsigned int silc_pkcs_get_key_len(SilcPKCS self)
125 {
126   return self->key_len;
127 }
128
129 /* Returns SILC style public key */
130
131 unsigned char *silc_pkcs_get_public_key(SilcPKCS pkcs, unsigned int *len)
132 {
133   return pkcs->pkcs->get_public_key(pkcs->context, len);
134 }
135
136 /* Returns SILC style private key */
137
138 unsigned char *silc_pkcs_get_private_key(SilcPKCS pkcs, unsigned int *len)
139 {
140   return pkcs->pkcs->get_private_key(pkcs->context, len);
141 }
142
143 /* Sets public key */
144 /* XXX rewrite */
145
146 int silc_pkcs_set_public_key(SilcPKCS pkcs, unsigned char *pk, 
147                              unsigned int pk_len)
148 {
149   return pkcs->pkcs->set_public_key(pkcs->context, pk, pk_len);
150 }
151
152 /* Sets private key */
153
154 int silc_pkcs_set_private_key(SilcPKCS pkcs, unsigned char *prv, 
155                               unsigned int prv_len)
156 {
157   return pkcs->pkcs->set_private_key(pkcs->context, prv, prv_len);
158 }
159
160 /* Saves public key into file */
161
162 int silc_pkcs_save_public_key(SilcPKCS pkcs, char *filename,
163                               unsigned char *pk, unsigned int pk_len)
164 {
165   SilcBuffer buf;
166   int ret = TRUE;
167
168   buf = silc_buffer_alloc(strlen(pkcs->pkcs->name) + 2 + pk_len
169                           + strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) 
170                           + strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
171
172   silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
173
174   silc_buffer_format(buf,
175                      SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
176                      SILC_STR_UI32_STRING(pkcs->pkcs->name),
177                      SILC_STR_UI_SHORT(pk_len),
178                      SILC_STR_UI_XNSTRING(pk, pk_len),
179                      SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
180                      SILC_STR_END);
181
182   /* Save into a file */
183   if (silc_file_write(filename, buf->data, buf->len)) {
184     ret = FALSE;
185     goto out;
186   }
187
188  out:
189   silc_buffer_free(buf);
190   return ret;
191 }
192
193 /* XXX The buffer should be encrypted */
194 /* XXX rewrite */
195
196 int silc_pkcs_save_private_key(SilcPKCS pkcs, char *filename,
197                                unsigned char *prv, unsigned int prv_len,
198                                char *passphrase)
199 {
200   SilcBuffer buf;
201   int ret = TRUE;
202
203   buf = silc_buffer_alloc(strlen(pkcs->pkcs->name) + 2 + prv_len
204                           + strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) 
205                           + strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
206   silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
207
208   silc_buffer_format(buf,
209                      SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
210                      SILC_STR_UI32_STRING(pkcs->pkcs->name),
211                      SILC_STR_UI_SHORT(prv_len),
212                      SILC_STR_UI_XNSTRING(prv, prv_len),
213                      SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
214                      SILC_STR_END);
215
216   /* Save into a file */
217   if (silc_file_write(filename, buf->data, buf->len)) {
218     ret = FALSE;
219     goto out;
220   }
221
222  out:
223   silc_buffer_free(buf);
224   return ret;
225 }
226
227 /* Loads public key from file and allocates new PKCS object and
228    sets the loaded key into it. */
229
230 int silc_pkcs_load_public_key(char *filename, SilcPKCS *ret_pkcs)
231 {
232
233   return TRUE;
234 }
235
236 /* Loads private key from file and allocates new PKCS object and
237    sets the loaded key into it. */
238
239 int silc_pkcs_load_private_key(char *filename, SilcPKCS *ret_pkcs)
240 {
241
242   return TRUE;
243 }