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 | **/ |
47 | int gnutls_pcert_import_x509 (gnutls_pcert_st* pcert, |
48 | gnutls_x509_crt_t crt, unsigned int flags) |
49 | { |
50 | int 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 | |
82 | cleanup: |
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 | **/ |
107 | int |
108 | gnutls_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 | { |
113 | int ret; |
114 | unsigned int i = 0, j; |
115 | gnutls_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 | |
142 | cleanup_pcert: |
143 | for (j=0;j<i;j++) |
144 | gnutls_pcert_deinit(&pcerts[j]); |
145 | |
146 | cleanup: |
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 | **/ |
171 | int 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 | { |
175 | int ret; |
176 | gnutls_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 | |
200 | cleanup: |
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 | **/ |
223 | int gnutls_pcert_import_openpgp (gnutls_pcert_st* pcert, |
224 | gnutls_openpgp_crt_t crt, unsigned int flags) |
225 | { |
226 | int ret; |
227 | size_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 | |
275 | cleanup: |
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 | **/ |
298 | int 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 | { |
304 | int ret; |
305 | gnutls_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 | |
337 | cleanup: |
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 | **/ |
353 | void |
354 | gnutls_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 | */ |
364 | int |
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 | |