1/*
2 * Copyright (C) 2011-2012 Free Software Foundation, Inc.
3 *
4 * Author: Nikos Mavrogiannopoulos
5 *
6 * This file is part of GnuTLS.
7 *
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
20 *
21 */
22
23#include <gnutls_int.h>
24#include <gnutls_errors.h>
25#include <auth/cert.h>
26#include <gnutls_x509.h>
27#include "x509/x509_int.h"
28#ifdef ENABLE_OPENPGP
29#include "openpgp/gnutls_openpgp.h"
30#endif
31
32/**
33 * gnutls_pcert_import_x509:
34 * @pcert: The pcert structure
35 * @crt: The raw certificate to be imported
36 * @flags: zero for now
37 *
38 * This convenience function will import the given certificate to a
39 * #gnutls_pcert_st structure. The structure must be deinitialized
40 * afterwards using gnutls_pcert_deinit();
41 *
42 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
43 * negative error value.
44 *
45 * Since: 3.0
46 **/
47int gnutls_pcert_import_x509 (gnutls_pcert_st* pcert,
48 gnutls_x509_crt_t crt, unsigned int flags)
49{
50int ret;
51
52 memset(pcert, 0, sizeof(*pcert));
53
54 pcert->type = GNUTLS_CRT_X509;
55 pcert->cert.data = NULL;
56
57 ret = gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_DER, &pcert->cert);
58 if (ret < 0)
59 {
60 ret = gnutls_assert_val(ret);
61 goto cleanup;
62 }
63
64 ret = gnutls_pubkey_init(&pcert->pubkey);
65 if (ret < 0)
66 {
67 ret = gnutls_assert_val(ret);
68 goto cleanup;
69 }
70
71 ret = gnutls_pubkey_import_x509(pcert->pubkey, crt, 0);
72 if (ret < 0)
73 {
74 gnutls_pubkey_deinit(pcert->pubkey);
75 pcert->pubkey = NULL;
76 ret = gnutls_assert_val(ret);
77 goto cleanup;
78 }
79
80 return 0;
81
82cleanup:
83 _gnutls_free_datum(&pcert->cert);
84
85 return ret;
86}
87
88/**
89 * gnutls_pcert_list_import_x509_raw:
90 * @pcerts: The structures to store the parsed certificate. Must not be initialized.
91 * @pcert_max: Initially must hold the maximum number of certs. It will be updated with the number of certs available.
92 * @data: The certificates.
93 * @format: One of DER or PEM.
94 * @flags: must be (0) or an OR'd sequence of gnutls_certificate_import_flags.
95 *
96 * This function will convert the given PEM encoded certificate list
97 * to the native gnutls_x509_crt_t format. The output will be stored
98 * in @certs. They will be automatically initialized.
99 *
100 * If the Certificate is PEM encoded it should have a header of "X509
101 * CERTIFICATE", or "CERTIFICATE".
102 *
103 * Returns: the number of certificates read or a negative error value.
104 *
105 * Since: 3.0
106 **/
107int
108gnutls_pcert_list_import_x509_raw (gnutls_pcert_st * pcerts,
109 unsigned int *pcert_max,
110 const gnutls_datum_t * data,
111 gnutls_x509_crt_fmt_t format, unsigned int flags)
112{
113int ret;
114unsigned int i = 0, j;
115gnutls_x509_crt_t *crt;
116
117 crt = gnutls_malloc((*pcert_max) * sizeof(gnutls_x509_crt_t));
118
119 if (crt == NULL)
120 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
121
122 ret = gnutls_x509_crt_list_import( crt, pcert_max, data, format, flags);
123 if (ret < 0)
124 {
125 ret = gnutls_assert_val(ret);
126 goto cleanup;
127 }
128
129 for (i=0;i<*pcert_max;i++)
130 {
131 ret = gnutls_pcert_import_x509(&pcerts[i], crt[i], flags);
132 if (ret < 0)
133 {
134 ret = gnutls_assert_val(ret);
135 goto cleanup_pcert;
136 }
137 }
138
139 ret = 0;
140 goto cleanup;
141
142cleanup_pcert:
143 for (j=0;j<i;j++)
144 gnutls_pcert_deinit(&pcerts[j]);
145
146cleanup:
147 for (i=0;i<*pcert_max;i++)
148 gnutls_x509_crt_deinit(crt[i]);
149
150 gnutls_free(crt);
151 return ret;
152
153}
154
155/**
156 * gnutls_pcert_import_x509_raw:
157 * @pcert: The pcert structure
158 * @cert: The raw certificate to be imported
159 * @format: The format of the certificate
160 * @flags: zero for now
161 *
162 * This convenience function will import the given certificate to a
163 * #gnutls_pcert_st structure. The structure must be deinitialized
164 * afterwards using gnutls_pcert_deinit();
165 *
166 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
167 * negative error value.
168 *
169 * Since: 3.0
170 **/
171int gnutls_pcert_import_x509_raw (gnutls_pcert_st *pcert,
172 const gnutls_datum_t* cert,
173 gnutls_x509_crt_fmt_t format, unsigned int flags)
174{
175int ret;
176gnutls_x509_crt_t crt;
177
178 memset(pcert, 0, sizeof(*pcert));
179
180 ret = gnutls_x509_crt_init(&crt);
181 if (ret < 0)
182 return gnutls_assert_val(ret);
183
184 ret = gnutls_x509_crt_import(crt, cert, format);
185 if (ret < 0)
186 {
187 ret = gnutls_assert_val(ret);
188 goto cleanup;
189 }
190
191 ret = gnutls_pcert_import_x509(pcert, crt, flags);
192 if (ret < 0)
193 {
194 ret = gnutls_assert_val(ret);
195 goto cleanup;
196 }
197
198 ret = 0;
199
200cleanup:
201 gnutls_x509_crt_deinit(crt);
202
203 return ret;
204}
205
206#ifdef ENABLE_OPENPGP
207
208/**
209 * gnutls_pcert_import_openpgp:
210 * @pcert: The pcert structure
211 * @crt: The raw certificate to be imported
212 * @flags: zero for now
213 *
214 * This convenience function will import the given certificate to a
215 * #gnutls_pcert_st structure. The structure must be deinitialized
216 * afterwards using gnutls_pcert_deinit();
217 *
218 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
219 * negative error value.
220 *
221 * Since: 3.0
222 **/
223int gnutls_pcert_import_openpgp (gnutls_pcert_st* pcert,
224 gnutls_openpgp_crt_t crt, unsigned int flags)
225{
226int ret;
227size_t sz;
228
229 memset(pcert, 0, sizeof(*pcert));
230
231 pcert->type = GNUTLS_CRT_OPENPGP;
232 pcert->cert.data = NULL;
233
234 sz = 0;
235 ret = gnutls_openpgp_crt_export(crt, GNUTLS_OPENPGP_FMT_RAW, NULL, &sz);
236 if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
237 {
238 ret = gnutls_assert_val(ret);
239 goto cleanup;
240 }
241
242 pcert->cert.data = gnutls_malloc(sz);
243 if (pcert->cert.data == NULL)
244 {
245 ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
246 goto cleanup;
247 }
248
249 ret = gnutls_openpgp_crt_export(crt, GNUTLS_X509_FMT_DER, pcert->cert.data, &sz);
250 if (ret < 0)
251 {
252 ret = gnutls_assert_val(ret);
253 goto cleanup;
254 }
255 pcert->cert.size = sz;
256
257 ret = gnutls_pubkey_init(&pcert->pubkey);
258 if (ret < 0)
259 {
260 ret = gnutls_assert_val(ret);
261 goto cleanup;
262 }
263
264 ret = gnutls_pubkey_import_openpgp(pcert->pubkey, crt, 0);
265 if (ret < 0)
266 {
267 gnutls_pubkey_deinit(pcert->pubkey);
268 pcert->pubkey = NULL;
269 ret = gnutls_assert_val(ret);
270 goto cleanup;
271 }
272
273 return 0;
274
275cleanup:
276 _gnutls_free_datum(&pcert->cert);
277
278 return ret;
279}
280
281/**
282 * gnutls_pcert_import_openpgp_raw:
283 * @pcert: The pcert structure
284 * @cert: The raw certificate to be imported
285 * @format: The format of the certificate
286 * @keyid: The key ID to use (NULL for the master key)
287 * @flags: zero for now
288 *
289 * This convenience function will import the given certificate to a
290 * #gnutls_pcert_st structure. The structure must be deinitialized
291 * afterwards using gnutls_pcert_deinit();
292 *
293 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
294 * negative error value.
295 *
296 * Since: 3.0
297 **/
298int gnutls_pcert_import_openpgp_raw (gnutls_pcert_st *pcert,
299 const gnutls_datum_t* cert,
300 gnutls_openpgp_crt_fmt_t format,
301 gnutls_openpgp_keyid_t keyid,
302 unsigned int flags)
303{
304int ret;
305gnutls_openpgp_crt_t crt;
306
307 memset(pcert, 0, sizeof(*pcert));
308
309 pcert->cert.data = NULL;
310
311 ret = gnutls_openpgp_crt_init(&crt);
312 if (ret < 0)
313 return gnutls_assert_val(ret);
314
315 ret = gnutls_openpgp_crt_import(crt, cert, format);
316 if (ret < 0)
317 {
318 ret = gnutls_assert_val(ret);
319 goto cleanup;
320 }
321
322 ret = gnutls_openpgp_crt_set_preferred_key_id(crt, keyid);
323 if (ret < 0)
324 {
325 ret = gnutls_assert_val(ret);
326 goto cleanup;
327 }
328
329 ret = gnutls_pcert_import_openpgp(pcert, crt, flags);
330 if (ret < 0)
331 {
332 ret = gnutls_assert_val(ret);
333 goto cleanup;
334 }
335 ret = 0;
336
337cleanup:
338 gnutls_openpgp_crt_deinit(crt);
339
340 return ret;
341}
342
343#endif
344
345/**
346 * gnutls_pcert_deinit:
347 * @pcert: The structure to be deinitialized
348 *
349 * This function will deinitialize a pcert structure.
350 *
351 * Since: 3.0
352 **/
353void
354gnutls_pcert_deinit (gnutls_pcert_st *pcert)
355{
356 gnutls_pubkey_deinit(pcert->pubkey);
357 pcert->pubkey = NULL;
358 _gnutls_free_datum(&pcert->cert);
359}
360
361/* Converts the first certificate for the cert_auth_info structure
362 * to a pcert.
363 */
364int
365_gnutls_get_auth_info_pcert (gnutls_pcert_st* pcert,
366 gnutls_certificate_type_t type,
367 cert_auth_info_t info)
368{
369 switch (type)
370 {
371 case GNUTLS_CRT_X509:
372 return gnutls_pcert_import_x509_raw(pcert, &info->raw_certificate_list[0],
373 GNUTLS_X509_FMT_DER, GNUTLS_PCERT_NO_CERT);
374#ifdef ENABLE_OPENPGP
375 case GNUTLS_CRT_OPENPGP:
376 return gnutls_pcert_import_openpgp_raw(pcert,
377 &info->raw_certificate_list[0],
378 GNUTLS_OPENPGP_FMT_RAW,
379 info->subkey_id, GNUTLS_PCERT_NO_CERT);
380#endif
381 default:
382 gnutls_assert ();
383 return GNUTLS_E_INTERNAL_ERROR;
384 }
385}
386