diff options
Diffstat (limited to 'src/daemon/https/x509')
35 files changed, 24851 insertions, 0 deletions
diff --git a/src/daemon/https/x509/Makefile.am b/src/daemon/https/x509/Makefile.am new file mode 100644 index 00000000..c3a30f03 --- /dev/null +++ b/src/daemon/https/x509/Makefile.am | |||
@@ -0,0 +1,36 @@ | |||
1 | |||
2 | AM_CPPFLAGS = -I./includes \ | ||
3 | -I$(top_srcdir)/src/daemon/https/includes \ | ||
4 | -I$(top_srcdir)/src/daemon/https/minitasn1 \ | ||
5 | -I$(top_srcdir)/src/daemon/https/lgl \ | ||
6 | -I$(top_srcdir)/src/daemon/https/x509 \ | ||
7 | -I$(top_srcdir)/src/daemon/https/tls | ||
8 | |||
9 | noinst_LTLIBRARIES = libx509.la | ||
10 | |||
11 | libx509_la_LDFLAGS = -lgcrypt | ||
12 | # -l $(top_srcdir)/src/daemon/https/lgl/liblgl.la | ||
13 | |||
14 | libx509_la_SOURCES = \ | ||
15 | common.c \ | ||
16 | crq.c \ | ||
17 | crl.c \ | ||
18 | crl_write.c \ | ||
19 | dn.c \ | ||
20 | dsa.c \ | ||
21 | extensions.c \ | ||
22 | mpi.c \ | ||
23 | pkcs12_bag.c \ | ||
24 | pkcs12.c \ | ||
25 | pkcs12_encr.c \ | ||
26 | pkcs7.c \ | ||
27 | x509_privkey.c \ | ||
28 | privkey_pkcs8.c \ | ||
29 | rfc2818_hostname.c \ | ||
30 | sign.c \ | ||
31 | x509_verify.c \ | ||
32 | x509.c \ | ||
33 | x509_write.c | ||
34 | # output.c | ||
35 | |||
36 | |||
diff --git a/src/daemon/https/x509/common.c b/src/daemon/https/x509/common.c new file mode 100644 index 00000000..98a655c7 --- /dev/null +++ b/src/daemon/https/x509/common.c | |||
@@ -0,0 +1,1491 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <gnutls_int.h> | ||
26 | #include <libtasn1.h> | ||
27 | #include <gnutls_datum.h> | ||
28 | #include <gnutls_global.h> | ||
29 | #include <gnutls_errors.h> | ||
30 | #include <gnutls_str.h> | ||
31 | #include <gnutls_x509.h> | ||
32 | #include <gnutls_num.h> | ||
33 | #include <x509_b64.h> | ||
34 | #include <common.h> | ||
35 | #include <mpi.h> | ||
36 | #include <time.h> | ||
37 | |||
38 | typedef struct _oid2string | ||
39 | { | ||
40 | const char *oid; | ||
41 | const char *ldap_desc; | ||
42 | int choice; /* of type DirectoryString */ | ||
43 | int printable; | ||
44 | } oid2string; | ||
45 | |||
46 | /* This list contains all the OIDs that may be | ||
47 | * contained in a rdnSequence and are printable. | ||
48 | */ | ||
49 | static const oid2string _oid2str[] = { | ||
50 | /* PKIX | ||
51 | */ | ||
52 | {"1.3.6.1.5.5.7.9.1", | ||
53 | "dateOfBirth", | ||
54 | 0, | ||
55 | 1}, | ||
56 | {"1.3.6.1.5.5.7.9.2", | ||
57 | "placeOfBirth", | ||
58 | 0, | ||
59 | 1}, | ||
60 | {"1.3.6.1.5.5.7.9.3", | ||
61 | "gender", | ||
62 | 0, | ||
63 | 1}, | ||
64 | {"1.3.6.1.5.5.7.9.4", | ||
65 | "countryOfCitizenship", | ||
66 | 0, | ||
67 | 1}, | ||
68 | {"1.3.6.1.5.5.7.9.5", | ||
69 | "countryOfResidence", | ||
70 | 0, | ||
71 | 1}, | ||
72 | |||
73 | {"2.5.4.6", | ||
74 | "C", | ||
75 | 0, | ||
76 | 1}, | ||
77 | {"2.5.4.9", | ||
78 | "STREET", | ||
79 | 1, | ||
80 | 1}, | ||
81 | {"2.5.4.12", | ||
82 | "T", | ||
83 | 1, | ||
84 | 1}, | ||
85 | {"2.5.4.10", | ||
86 | "O", | ||
87 | 1, | ||
88 | 1}, | ||
89 | {"2.5.4.11", | ||
90 | "OU", | ||
91 | 1, | ||
92 | 1}, | ||
93 | {"2.5.4.3", | ||
94 | "CN", | ||
95 | 1, | ||
96 | 1}, | ||
97 | {"2.5.4.7", | ||
98 | "L", | ||
99 | 1, | ||
100 | 1}, | ||
101 | {"2.5.4.8", | ||
102 | "ST", | ||
103 | 1, | ||
104 | 1}, | ||
105 | |||
106 | {"2.5.4.5", | ||
107 | "serialNumber", | ||
108 | 0, | ||
109 | 1}, | ||
110 | {"2.5.4.20", | ||
111 | "telephoneNumber", | ||
112 | 0, | ||
113 | 1}, | ||
114 | {"2.5.4.4", | ||
115 | "surName", | ||
116 | 1, | ||
117 | 1}, | ||
118 | {"2.5.4.43", | ||
119 | "initials", | ||
120 | 1, | ||
121 | 1}, | ||
122 | {"2.5.4.44", | ||
123 | "generationQualifier", | ||
124 | 1, | ||
125 | 1}, | ||
126 | {"2.5.4.42", | ||
127 | "givenName", | ||
128 | 1, | ||
129 | 1}, | ||
130 | {"2.5.4.65", | ||
131 | "pseudonym", | ||
132 | 1, | ||
133 | 1}, | ||
134 | {"2.5.4.46", | ||
135 | "dnQualifier", | ||
136 | 0, | ||
137 | 1}, | ||
138 | |||
139 | {"0.9.2342.19200300.100.1.25", | ||
140 | "DC", | ||
141 | 0, | ||
142 | 1}, | ||
143 | {"0.9.2342.19200300.100.1.1", | ||
144 | "UID", | ||
145 | 1, | ||
146 | 1}, | ||
147 | |||
148 | /* PKCS #9 | ||
149 | */ | ||
150 | {"1.2.840.113549.1.9.1", | ||
151 | "EMAIL", | ||
152 | 0, | ||
153 | 1}, | ||
154 | {"1.2.840.113549.1.9.7", | ||
155 | NULL, | ||
156 | 1, | ||
157 | 1}, | ||
158 | |||
159 | /* friendly name */ | ||
160 | {"1.2.840.113549.1.9.20", | ||
161 | NULL, | ||
162 | 0, | ||
163 | 1}, | ||
164 | {NULL, | ||
165 | NULL, | ||
166 | 0, | ||
167 | 0} | ||
168 | }; | ||
169 | |||
170 | /* Returns 1 if the data defined by the OID are printable. | ||
171 | */ | ||
172 | int | ||
173 | _gnutls_x509_oid_data_printable (const char *oid) | ||
174 | { | ||
175 | int i = 0; | ||
176 | |||
177 | do | ||
178 | { | ||
179 | if (strcmp (_oid2str[i].oid, oid) == 0) | ||
180 | return _oid2str[i].printable; | ||
181 | i++; | ||
182 | } | ||
183 | while (_oid2str[i].oid != NULL); | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * gnutls_x509_dn_oid_known - This function will return true if the given OID is known | ||
190 | * @oid: holds an Object Identifier in a null terminated string | ||
191 | * | ||
192 | * This function will inform about known DN OIDs. This is useful since functions | ||
193 | * like gnutls_x509_crt_set_dn_by_oid() use the information on known | ||
194 | * OIDs to properly encode their input. Object Identifiers that are not | ||
195 | * known are not encoded by these functions, and their input is stored directly | ||
196 | * into the ASN.1 structure. In that case of unknown OIDs, you have | ||
197 | * the responsibility of DER encoding your data. | ||
198 | * | ||
199 | * Returns 1 on known OIDs and 0 otherwise. | ||
200 | * | ||
201 | **/ | ||
202 | int | ||
203 | gnutls_x509_dn_oid_known (const char *oid) | ||
204 | { | ||
205 | int i = 0; | ||
206 | |||
207 | do | ||
208 | { | ||
209 | if (strcmp (_oid2str[i].oid, oid) == 0) | ||
210 | return 1; | ||
211 | i++; | ||
212 | } | ||
213 | while (_oid2str[i].oid != NULL); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | /* Returns 1 if the data defined by the OID are of a choice | ||
219 | * type. | ||
220 | */ | ||
221 | int | ||
222 | _gnutls_x509_oid_data_choice (const char *oid) | ||
223 | { | ||
224 | int i = 0; | ||
225 | |||
226 | do | ||
227 | { | ||
228 | if (strcmp (_oid2str[i].oid, oid) == 0) | ||
229 | return _oid2str[i].choice; | ||
230 | i++; | ||
231 | } | ||
232 | while (_oid2str[i].oid != NULL); | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | const char * | ||
238 | _gnutls_x509_oid2ldap_string (const char *oid) | ||
239 | { | ||
240 | int i = 0; | ||
241 | |||
242 | do | ||
243 | { | ||
244 | if (strcmp (_oid2str[i].oid, oid) == 0) | ||
245 | return _oid2str[i].ldap_desc; | ||
246 | i++; | ||
247 | } | ||
248 | while (_oid2str[i].oid != NULL); | ||
249 | |||
250 | return NULL; | ||
251 | } | ||
252 | |||
253 | /* This function will convert an attribute value, specified by the OID, | ||
254 | * to a string. The result will be a null terminated string. | ||
255 | * | ||
256 | * res may be null. This will just return the res_size, needed to | ||
257 | * hold the string. | ||
258 | */ | ||
259 | int | ||
260 | _gnutls_x509_oid_data2string (const char *oid, | ||
261 | void *value, | ||
262 | int value_size, char *res, size_t * res_size) | ||
263 | { | ||
264 | char str[MAX_STRING_LEN], tmpname[128]; | ||
265 | const char *ANAME = NULL; | ||
266 | int CHOICE = -1, len = -1, result; | ||
267 | ASN1_TYPE tmpasn = ASN1_TYPE_EMPTY; | ||
268 | char asn1_err[MAX_ERROR_DESCRIPTION_SIZE] = ""; | ||
269 | |||
270 | if (value == NULL || value_size <= 0 || res_size == NULL) | ||
271 | { | ||
272 | gnutls_assert (); | ||
273 | return GNUTLS_E_INVALID_REQUEST; | ||
274 | } | ||
275 | |||
276 | if (_gnutls_x509_oid_data_printable (oid) == 0) | ||
277 | { | ||
278 | gnutls_assert (); | ||
279 | return GNUTLS_E_INTERNAL_ERROR; | ||
280 | } | ||
281 | |||
282 | ANAME = asn1_find_structure_from_oid (_gnutls_get_pkix (), oid); | ||
283 | CHOICE = _gnutls_x509_oid_data_choice (oid); | ||
284 | |||
285 | if (ANAME == NULL) | ||
286 | { | ||
287 | gnutls_assert (); | ||
288 | return GNUTLS_E_INTERNAL_ERROR; | ||
289 | } | ||
290 | |||
291 | _gnutls_str_cpy (str, sizeof (str), "PKIX1."); | ||
292 | _gnutls_str_cat (str, sizeof (str), ANAME); | ||
293 | |||
294 | if ((result = asn1_create_element (_gnutls_get_pkix (), str, | ||
295 | &tmpasn)) != ASN1_SUCCESS) | ||
296 | { | ||
297 | gnutls_assert (); | ||
298 | return _gnutls_asn2err (result); | ||
299 | } | ||
300 | |||
301 | if ((result = asn1_der_decoding (&tmpasn, value, value_size, asn1_err)) | ||
302 | != ASN1_SUCCESS) | ||
303 | { | ||
304 | gnutls_assert (); | ||
305 | _gnutls_x509_log ("asn1_der_decoding: %s:%s\n", str, asn1_err); | ||
306 | asn1_delete_structure (&tmpasn); | ||
307 | return _gnutls_asn2err (result); | ||
308 | } | ||
309 | |||
310 | /* If this is a choice then we read the choice. Otherwise it | ||
311 | * is the value; | ||
312 | */ | ||
313 | len = sizeof (str) - 1; | ||
314 | if ((result = asn1_read_value (tmpasn, "", str, &len)) != ASN1_SUCCESS) | ||
315 | { /* CHOICE */ | ||
316 | gnutls_assert (); | ||
317 | asn1_delete_structure (&tmpasn); | ||
318 | return _gnutls_asn2err (result); | ||
319 | } | ||
320 | |||
321 | if (CHOICE == 0) | ||
322 | { | ||
323 | str[len] = 0; | ||
324 | |||
325 | if (res) | ||
326 | _gnutls_str_cpy (res, *res_size, str); | ||
327 | *res_size = len; | ||
328 | |||
329 | asn1_delete_structure (&tmpasn); | ||
330 | } | ||
331 | else | ||
332 | { /* CHOICE */ | ||
333 | int non_printable = 0, teletex = 0; | ||
334 | str[len] = 0; | ||
335 | |||
336 | /* Note that we do not support strings other than | ||
337 | * UTF-8 (thus ASCII as well). | ||
338 | */ | ||
339 | if (strcmp (str, "printableString") != 0 | ||
340 | && strcmp (str, "ia5String") != 0 | ||
341 | && strcmp (str, "utf8String") != 0) | ||
342 | { | ||
343 | non_printable = 1; | ||
344 | } | ||
345 | if (strcmp (str, "teletexString") == 0) | ||
346 | teletex = 1; | ||
347 | |||
348 | _gnutls_str_cpy (tmpname, sizeof (tmpname), str); | ||
349 | |||
350 | len = sizeof (str) - 1; | ||
351 | if ((result = asn1_read_value (tmpasn, tmpname, str, &len)) | ||
352 | != ASN1_SUCCESS) | ||
353 | { | ||
354 | asn1_delete_structure (&tmpasn); | ||
355 | return _gnutls_asn2err (result); | ||
356 | } | ||
357 | |||
358 | asn1_delete_structure (&tmpasn); | ||
359 | |||
360 | if (teletex != 0) | ||
361 | { | ||
362 | int ascii = 0, i; | ||
363 | /* HACK: if the teletex string contains only ascii | ||
364 | * characters then treat it as printable. | ||
365 | */ | ||
366 | for (i = 0; i < len; i++) | ||
367 | if (!isascii (str[i])) | ||
368 | ascii = 1; | ||
369 | |||
370 | if (ascii == 0) | ||
371 | non_printable = 0; | ||
372 | } | ||
373 | |||
374 | if (res) | ||
375 | { | ||
376 | if (non_printable == 0) | ||
377 | { | ||
378 | str[len] = 0; | ||
379 | _gnutls_str_cpy (res, *res_size, str); | ||
380 | *res_size = len; | ||
381 | } | ||
382 | else | ||
383 | { | ||
384 | result = _gnutls_x509_data2hex (str, len, res, res_size); | ||
385 | if (result < 0) | ||
386 | { | ||
387 | gnutls_assert (); | ||
388 | return result; | ||
389 | } | ||
390 | } | ||
391 | } | ||
392 | |||
393 | } | ||
394 | |||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | /* Converts a data string to an LDAP rfc2253 hex string | ||
399 | * something like '#01020304' | ||
400 | */ | ||
401 | int | ||
402 | _gnutls_x509_data2hex (const opaque * data, | ||
403 | size_t data_size, opaque * out, size_t * sizeof_out) | ||
404 | { | ||
405 | char *res; | ||
406 | char escaped[MAX_STRING_LEN]; | ||
407 | |||
408 | if (2 * data_size + 1 > MAX_STRING_LEN) | ||
409 | { | ||
410 | gnutls_assert (); | ||
411 | return GNUTLS_E_INTERNAL_ERROR; | ||
412 | } | ||
413 | |||
414 | res = _gnutls_bin2hex (data, data_size, escaped, sizeof (escaped)); | ||
415 | |||
416 | if (res) | ||
417 | { | ||
418 | unsigned int size = strlen (res) + 1; | ||
419 | if (size + 1 > *sizeof_out) | ||
420 | { | ||
421 | *sizeof_out = size; | ||
422 | return GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
423 | } | ||
424 | *sizeof_out = size; /* -1 for the null +1 for the '#' */ | ||
425 | |||
426 | if (out) | ||
427 | { | ||
428 | strcpy (out, "#"); | ||
429 | strcat (out, res); | ||
430 | } | ||
431 | |||
432 | return 0; | ||
433 | } | ||
434 | else | ||
435 | { | ||
436 | gnutls_assert (); | ||
437 | return GNUTLS_E_INTERNAL_ERROR; | ||
438 | } | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | /* TIME functions | ||
444 | * Convertions between generalized or UTC time to time_t | ||
445 | * | ||
446 | */ | ||
447 | |||
448 | /* This is an emulations of the struct tm. | ||
449 | * Since we do not use libc's functions, we don't need to | ||
450 | * depend on the libc structure. | ||
451 | */ | ||
452 | typedef struct fake_tm | ||
453 | { | ||
454 | int tm_mon; | ||
455 | int tm_year; /* FULL year - ie 1971 */ | ||
456 | int tm_mday; | ||
457 | int tm_hour; | ||
458 | int tm_min; | ||
459 | int tm_sec; | ||
460 | } fake_tm; | ||
461 | |||
462 | /* The mktime_utc function is due to Russ Allbery (rra@stanford.edu), | ||
463 | * who placed it under public domain: | ||
464 | */ | ||
465 | |||
466 | /* The number of days in each month. | ||
467 | */ | ||
468 | static const int MONTHDAYS[] = { 31, | ||
469 | 28, | ||
470 | 31, | ||
471 | 30, | ||
472 | 31, | ||
473 | 30, | ||
474 | 31, | ||
475 | 31, | ||
476 | 30, | ||
477 | 31, | ||
478 | 30, | ||
479 | 31 | ||
480 | }; | ||
481 | |||
482 | /* Whether a given year is a leap year. */ | ||
483 | #define ISLEAP(year) \ | ||
484 | (((year) % 4) == 0 && (((year) % 100) != 0 || ((year) % 400) == 0)) | ||
485 | |||
486 | /* | ||
487 | ** Given a struct tm representing a calendar time in UTC, convert it to | ||
488 | ** seconds since epoch. Returns (time_t) -1 if the time is not | ||
489 | ** convertable. Note that this function does not canonicalize the provided | ||
490 | ** struct tm, nor does it allow out of range values or years before 1970. | ||
491 | */ | ||
492 | static time_t | ||
493 | mktime_utc (const struct fake_tm *tm) | ||
494 | { | ||
495 | time_t result = 0; | ||
496 | int i; | ||
497 | |||
498 | /* We do allow some ill-formed dates, but we don't do anything special | ||
499 | * with them and our callers really shouldn't pass them to us. Do | ||
500 | * explicitly disallow the ones that would cause invalid array accesses | ||
501 | * or other algorithm problems. | ||
502 | */ | ||
503 | if (tm->tm_mon < 0 || tm->tm_mon > 11 || tm->tm_year < 1970) | ||
504 | return (time_t) - 1; | ||
505 | |||
506 | /* Convert to a time_t. | ||
507 | */ | ||
508 | for (i = 1970; i < tm->tm_year; i++) | ||
509 | result += 365 + ISLEAP (i); | ||
510 | for (i = 0; i < tm->tm_mon; i++) | ||
511 | result += MONTHDAYS[i]; | ||
512 | if (tm->tm_mon > 1 && ISLEAP (tm->tm_year)) | ||
513 | result++; | ||
514 | result = 24 * (result + tm->tm_mday - 1) + tm->tm_hour; | ||
515 | result = 60 * result + tm->tm_min; | ||
516 | result = 60 * result + tm->tm_sec; | ||
517 | return result; | ||
518 | } | ||
519 | |||
520 | /* this one will parse dates of the form: | ||
521 | * month|day|hour|minute|sec* (2 chars each) | ||
522 | * and year is given. Returns a time_t date. | ||
523 | */ | ||
524 | time_t | ||
525 | _gnutls_x509_time2gtime (const char *ttime, int year) | ||
526 | { | ||
527 | char xx[3]; | ||
528 | struct fake_tm etime; | ||
529 | time_t ret; | ||
530 | |||
531 | if (strlen (ttime) < 8) | ||
532 | { | ||
533 | gnutls_assert (); | ||
534 | return (time_t) - 1; | ||
535 | } | ||
536 | |||
537 | etime.tm_year = year; | ||
538 | |||
539 | /* In order to work with 32 bit | ||
540 | * time_t. | ||
541 | */ | ||
542 | if (sizeof (time_t) <= 4 && etime.tm_year >= 2038) | ||
543 | return (time_t) 2145914603; /* 2037-12-31 23:23:23 */ | ||
544 | |||
545 | xx[2] = 0; | ||
546 | |||
547 | /* get the month | ||
548 | */ | ||
549 | memcpy (xx, ttime, 2); /* month */ | ||
550 | etime.tm_mon = atoi (xx) - 1; | ||
551 | ttime += 2; | ||
552 | |||
553 | /* get the day | ||
554 | */ | ||
555 | memcpy (xx, ttime, 2); /* day */ | ||
556 | etime.tm_mday = atoi (xx); | ||
557 | ttime += 2; | ||
558 | |||
559 | /* get the hour | ||
560 | */ | ||
561 | memcpy (xx, ttime, 2); /* hour */ | ||
562 | etime.tm_hour = atoi (xx); | ||
563 | ttime += 2; | ||
564 | |||
565 | /* get the minutes | ||
566 | */ | ||
567 | memcpy (xx, ttime, 2); /* minutes */ | ||
568 | etime.tm_min = atoi (xx); | ||
569 | ttime += 2; | ||
570 | |||
571 | if (strlen (ttime) >= 2) | ||
572 | { | ||
573 | memcpy (xx, ttime, 2); | ||
574 | etime.tm_sec = atoi (xx); | ||
575 | ttime += 2; | ||
576 | } | ||
577 | else | ||
578 | etime.tm_sec = 0; | ||
579 | |||
580 | ret = mktime_utc (&etime); | ||
581 | |||
582 | return ret; | ||
583 | } | ||
584 | |||
585 | /* returns a time_t value that contains the given time. | ||
586 | * The given time is expressed as: | ||
587 | * YEAR(2)|MONTH(2)|DAY(2)|HOUR(2)|MIN(2)|SEC(2)* | ||
588 | * | ||
589 | * (seconds are optional) | ||
590 | */ | ||
591 | time_t | ||
592 | _gnutls_x509_utcTime2gtime (const char *ttime) | ||
593 | { | ||
594 | char xx[3]; | ||
595 | int year; | ||
596 | |||
597 | if (strlen (ttime) < 10) | ||
598 | { | ||
599 | gnutls_assert (); | ||
600 | return (time_t) - 1; | ||
601 | } | ||
602 | xx[2] = 0; | ||
603 | /* get the year | ||
604 | */ | ||
605 | memcpy (xx, ttime, 2); /* year */ | ||
606 | year = atoi (xx); | ||
607 | ttime += 2; | ||
608 | |||
609 | if (year > 49) | ||
610 | year += 1900; | ||
611 | else | ||
612 | year += 2000; | ||
613 | |||
614 | return _gnutls_x509_time2gtime (ttime, year); | ||
615 | } | ||
616 | |||
617 | /* returns a time value that contains the given time. | ||
618 | * The given time is expressed as: | ||
619 | * YEAR(2)|MONTH(2)|DAY(2)|HOUR(2)|MIN(2)|SEC(2) | ||
620 | */ | ||
621 | int | ||
622 | _gnutls_x509_gtime2utcTime (time_t gtime, char *str_time, int str_time_size) | ||
623 | { | ||
624 | size_t ret; | ||
625 | |||
626 | #ifdef HAVE_GMTIME_R | ||
627 | struct tm _tm; | ||
628 | |||
629 | gmtime_r (>ime, &_tm); | ||
630 | |||
631 | ret = strftime (str_time, str_time_size, "%y%m%d%H%M%SZ", &_tm); | ||
632 | #else | ||
633 | struct tm *_tm; | ||
634 | |||
635 | _tm = gmtime (>ime); | ||
636 | |||
637 | ret = strftime (str_time, str_time_size, "%y%m%d%H%M%SZ", _tm); | ||
638 | #endif | ||
639 | |||
640 | if (!ret) | ||
641 | { | ||
642 | gnutls_assert (); | ||
643 | return GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
644 | } | ||
645 | |||
646 | return 0; | ||
647 | |||
648 | } | ||
649 | |||
650 | /* returns a time_t value that contains the given time. | ||
651 | * The given time is expressed as: | ||
652 | * YEAR(4)|MONTH(2)|DAY(2)|HOUR(2)|MIN(2)|SEC(2)* | ||
653 | */ | ||
654 | time_t | ||
655 | _gnutls_x509_generalTime2gtime (const char *ttime) | ||
656 | { | ||
657 | char xx[5]; | ||
658 | int year; | ||
659 | |||
660 | if (strlen (ttime) < 12) | ||
661 | { | ||
662 | gnutls_assert (); | ||
663 | return (time_t) - 1; | ||
664 | } | ||
665 | |||
666 | if (strchr (ttime, 'Z') == 0) | ||
667 | { | ||
668 | gnutls_assert (); | ||
669 | /* sorry we don't support it yet | ||
670 | */ | ||
671 | return (time_t) - 1; | ||
672 | } | ||
673 | xx[4] = 0; | ||
674 | |||
675 | /* get the year | ||
676 | */ | ||
677 | memcpy (xx, ttime, 4); /* year */ | ||
678 | year = atoi (xx); | ||
679 | ttime += 4; | ||
680 | |||
681 | return _gnutls_x509_time2gtime (ttime, year); | ||
682 | |||
683 | } | ||
684 | |||
685 | /* Extracts the time in time_t from the ASN1_TYPE given. When should | ||
686 | * be something like "tbsCertList.thisUpdate". | ||
687 | */ | ||
688 | #define MAX_TIME 64 | ||
689 | time_t | ||
690 | _gnutls_x509_get_time (ASN1_TYPE c2, const char *when) | ||
691 | { | ||
692 | char ttime[MAX_TIME]; | ||
693 | char name[128]; | ||
694 | time_t c_time = (time_t) - 1; | ||
695 | int len, result; | ||
696 | |||
697 | _gnutls_str_cpy (name, sizeof (name), when); | ||
698 | |||
699 | len = sizeof (ttime) - 1; | ||
700 | if ((result = asn1_read_value (c2, name, ttime, &len)) < 0) | ||
701 | { | ||
702 | gnutls_assert (); | ||
703 | return (time_t) (-1); | ||
704 | } | ||
705 | |||
706 | /* CHOICE */ | ||
707 | if (strcmp (ttime, "generalTime") == 0) | ||
708 | { | ||
709 | |||
710 | _gnutls_str_cat (name, sizeof (name), ".generalTime"); | ||
711 | len = sizeof (ttime) - 1; | ||
712 | result = asn1_read_value (c2, name, ttime, &len); | ||
713 | if (result == ASN1_SUCCESS) | ||
714 | c_time = _gnutls_x509_generalTime2gtime (ttime); | ||
715 | } | ||
716 | else | ||
717 | { /* UTCTIME */ | ||
718 | |||
719 | _gnutls_str_cat (name, sizeof (name), ".utcTime"); | ||
720 | len = sizeof (ttime) - 1; | ||
721 | result = asn1_read_value (c2, name, ttime, &len); | ||
722 | if (result == ASN1_SUCCESS) | ||
723 | c_time = _gnutls_x509_utcTime2gtime (ttime); | ||
724 | } | ||
725 | |||
726 | /* We cannot handle dates after 2031 in 32 bit machines. | ||
727 | * a time_t of 64bits has to be used. | ||
728 | */ | ||
729 | |||
730 | if (result != ASN1_SUCCESS) | ||
731 | { | ||
732 | gnutls_assert (); | ||
733 | return (time_t) (-1); | ||
734 | } | ||
735 | return c_time; | ||
736 | } | ||
737 | |||
738 | /* Sets the time in time_t in the ASN1_TYPE given. Where should | ||
739 | * be something like "tbsCertList.thisUpdate". | ||
740 | */ | ||
741 | int | ||
742 | _gnutls_x509_set_time (ASN1_TYPE c2, const char *where, time_t tim) | ||
743 | { | ||
744 | char str_time[MAX_TIME]; | ||
745 | char name[128]; | ||
746 | int result, len; | ||
747 | |||
748 | _gnutls_str_cpy (name, sizeof (name), where); | ||
749 | |||
750 | if ((result = asn1_write_value (c2, name, "utcTime", 1)) < 0) | ||
751 | { | ||
752 | gnutls_assert (); | ||
753 | return _gnutls_asn2err (result); | ||
754 | } | ||
755 | |||
756 | result = _gnutls_x509_gtime2utcTime (tim, str_time, sizeof (str_time)); | ||
757 | if (result < 0) | ||
758 | { | ||
759 | gnutls_assert (); | ||
760 | return result; | ||
761 | } | ||
762 | |||
763 | _gnutls_str_cat (name, sizeof (name), ".utcTime"); | ||
764 | |||
765 | len = strlen (str_time); | ||
766 | result = asn1_write_value (c2, name, str_time, len); | ||
767 | if (result != ASN1_SUCCESS) | ||
768 | { | ||
769 | gnutls_assert (); | ||
770 | return _gnutls_asn2err (result); | ||
771 | } | ||
772 | |||
773 | return 0; | ||
774 | } | ||
775 | |||
776 | gnutls_x509_subject_alt_name_t | ||
777 | _gnutls_x509_san_find_type (char *str_type) | ||
778 | { | ||
779 | if (strcmp (str_type, "dNSName") == 0) | ||
780 | return GNUTLS_SAN_DNSNAME; | ||
781 | if (strcmp (str_type, "rfc822Name") == 0) | ||
782 | return GNUTLS_SAN_RFC822NAME; | ||
783 | if (strcmp (str_type, "uniformResourceIdentifier") == 0) | ||
784 | return GNUTLS_SAN_URI; | ||
785 | if (strcmp (str_type, "iPAddress") == 0) | ||
786 | return GNUTLS_SAN_IPADDRESS; | ||
787 | if (strcmp (str_type, "otherName") == 0) | ||
788 | return GNUTLS_SAN_OTHERNAME; | ||
789 | if (strcmp (str_type, "directoryName") == 0) | ||
790 | return GNUTLS_SAN_DN; | ||
791 | return (gnutls_x509_subject_alt_name_t) - 1; | ||
792 | } | ||
793 | |||
794 | /* A generic export function. Will export the given ASN.1 encoded data | ||
795 | * to PEM or DER raw data. | ||
796 | */ | ||
797 | int | ||
798 | _gnutls_x509_export_int (ASN1_TYPE asn1_data, | ||
799 | gnutls_x509_crt_fmt_t format, | ||
800 | char *pem_header, | ||
801 | unsigned char *output_data, | ||
802 | size_t * output_data_size) | ||
803 | { | ||
804 | int result, len; | ||
805 | |||
806 | if (format == GNUTLS_X509_FMT_DER) | ||
807 | { | ||
808 | |||
809 | if (output_data == NULL) | ||
810 | *output_data_size = 0; | ||
811 | |||
812 | len = *output_data_size; | ||
813 | |||
814 | if ((result = asn1_der_coding (asn1_data, "", output_data, &len, | ||
815 | NULL)) != ASN1_SUCCESS) | ||
816 | { | ||
817 | *output_data_size = len; | ||
818 | if (result == ASN1_MEM_ERROR) | ||
819 | { | ||
820 | return GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
821 | } | ||
822 | gnutls_assert (); | ||
823 | return _gnutls_asn2err (result); | ||
824 | } | ||
825 | |||
826 | *output_data_size = len; | ||
827 | |||
828 | } | ||
829 | else | ||
830 | { /* PEM */ | ||
831 | opaque *out; | ||
832 | gnutls_datum_t tmp; | ||
833 | |||
834 | result = _gnutls_x509_der_encode (asn1_data, "", &tmp, 0); | ||
835 | if (result < 0) | ||
836 | { | ||
837 | gnutls_assert (); | ||
838 | return result; | ||
839 | } | ||
840 | |||
841 | result = _gnutls_fbase64_encode (pem_header, tmp.data, tmp.size, &out); | ||
842 | |||
843 | _gnutls_free_datum (&tmp); | ||
844 | |||
845 | if (result < 0) | ||
846 | { | ||
847 | gnutls_assert (); | ||
848 | return result; | ||
849 | } | ||
850 | |||
851 | if (result == 0) | ||
852 | { /* oooops */ | ||
853 | gnutls_assert (); | ||
854 | return GNUTLS_E_INTERNAL_ERROR; | ||
855 | } | ||
856 | |||
857 | if ((unsigned) result > *output_data_size) | ||
858 | { | ||
859 | gnutls_assert (); | ||
860 | gnutls_free (out); | ||
861 | *output_data_size = result; | ||
862 | return GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
863 | } | ||
864 | |||
865 | *output_data_size = result; | ||
866 | |||
867 | if (output_data) | ||
868 | { | ||
869 | memcpy (output_data, out, result); | ||
870 | |||
871 | /* do not include the null character into output size. | ||
872 | */ | ||
873 | *output_data_size = result - 1; | ||
874 | } | ||
875 | gnutls_free (out); | ||
876 | |||
877 | } | ||
878 | |||
879 | return 0; | ||
880 | } | ||
881 | |||
882 | /* Decodes an octet string. Leave string_type null for a normal | ||
883 | * octet string. Otherwise put something like BMPString, PrintableString | ||
884 | * etc. | ||
885 | */ | ||
886 | int | ||
887 | _gnutls_x509_decode_octet_string (const char *string_type, | ||
888 | const opaque * der, | ||
889 | size_t der_size, | ||
890 | opaque * output, size_t * output_size) | ||
891 | { | ||
892 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
893 | int result, tmp_output_size; | ||
894 | char strname[64]; | ||
895 | |||
896 | if (string_type == NULL) | ||
897 | _gnutls_str_cpy (strname, sizeof (strname), "PKIX1.pkcs-7-Data"); | ||
898 | else | ||
899 | { | ||
900 | _gnutls_str_cpy (strname, sizeof (strname), "PKIX1."); | ||
901 | _gnutls_str_cat (strname, sizeof (strname), string_type); | ||
902 | } | ||
903 | |||
904 | if ((result = | ||
905 | asn1_create_element (_gnutls_get_pkix (), strname, | ||
906 | &c2)) != ASN1_SUCCESS) | ||
907 | { | ||
908 | gnutls_assert (); | ||
909 | result = _gnutls_asn2err (result); | ||
910 | goto cleanup; | ||
911 | } | ||
912 | |||
913 | result = asn1_der_decoding (&c2, der, der_size, NULL); | ||
914 | if (result != ASN1_SUCCESS) | ||
915 | { | ||
916 | gnutls_assert (); | ||
917 | result = _gnutls_asn2err (result); | ||
918 | goto cleanup; | ||
919 | } | ||
920 | |||
921 | tmp_output_size = *output_size; | ||
922 | result = asn1_read_value (c2, "", output, &tmp_output_size); | ||
923 | *output_size = tmp_output_size; | ||
924 | |||
925 | if (result != ASN1_SUCCESS) | ||
926 | { | ||
927 | gnutls_assert (); | ||
928 | result = _gnutls_asn2err (result); | ||
929 | goto cleanup; | ||
930 | } | ||
931 | |||
932 | return 0; | ||
933 | |||
934 | cleanup:if (c2) | ||
935 | asn1_delete_structure (&c2); | ||
936 | |||
937 | return result; | ||
938 | } | ||
939 | |||
940 | /* Reads a value from an ASN1 tree, and puts the output | ||
941 | * in an allocated variable in the given datum. | ||
942 | * flags == 0 do nothing with the DER output | ||
943 | * flags == 1 parse the DER output as OCTET STRING | ||
944 | * flags == 2 the value is a BIT STRING | ||
945 | */ | ||
946 | int | ||
947 | _gnutls_x509_read_value (ASN1_TYPE c, | ||
948 | const char *root, gnutls_datum_t * ret, int flags) | ||
949 | { | ||
950 | int len = 0, result; | ||
951 | size_t slen; | ||
952 | opaque *tmp = NULL; | ||
953 | |||
954 | result = asn1_read_value (c, root, NULL, &len); | ||
955 | if (result != ASN1_MEM_ERROR) | ||
956 | { | ||
957 | gnutls_assert (); | ||
958 | result = _gnutls_asn2err (result); | ||
959 | return result; | ||
960 | } | ||
961 | |||
962 | if (flags == 2) | ||
963 | len /= 8; | ||
964 | |||
965 | tmp = gnutls_malloc (len); | ||
966 | if (tmp == NULL) | ||
967 | { | ||
968 | gnutls_assert (); | ||
969 | result = GNUTLS_E_MEMORY_ERROR; | ||
970 | goto cleanup; | ||
971 | } | ||
972 | |||
973 | result = asn1_read_value (c, root, tmp, &len); | ||
974 | if (result != ASN1_SUCCESS) | ||
975 | { | ||
976 | gnutls_assert (); | ||
977 | result = _gnutls_asn2err (result); | ||
978 | goto cleanup; | ||
979 | } | ||
980 | |||
981 | if (flags == 2) | ||
982 | len /= 8; | ||
983 | |||
984 | /* Extract the OCTET STRING. | ||
985 | */ | ||
986 | |||
987 | if (flags == 1) | ||
988 | { | ||
989 | slen = len; | ||
990 | result = _gnutls_x509_decode_octet_string (NULL, tmp, slen, tmp, &slen); | ||
991 | if (result < 0) | ||
992 | { | ||
993 | gnutls_assert (); | ||
994 | goto cleanup; | ||
995 | } | ||
996 | len = slen; | ||
997 | } | ||
998 | |||
999 | ret->data = tmp; | ||
1000 | ret->size = len; | ||
1001 | |||
1002 | return 0; | ||
1003 | |||
1004 | cleanup:gnutls_free (tmp); | ||
1005 | return result; | ||
1006 | |||
1007 | } | ||
1008 | |||
1009 | /* DER Encodes the src ASN1_TYPE and stores it to | ||
1010 | * the given datum. If str is non null then the data are encoded as | ||
1011 | * an OCTET STRING. | ||
1012 | */ | ||
1013 | int | ||
1014 | _gnutls_x509_der_encode (ASN1_TYPE src, | ||
1015 | const char *src_name, gnutls_datum_t * res, int str) | ||
1016 | { | ||
1017 | int size, result; | ||
1018 | int asize; | ||
1019 | opaque *data = NULL; | ||
1020 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
1021 | |||
1022 | size = 0; | ||
1023 | result = asn1_der_coding (src, src_name, NULL, &size, NULL); | ||
1024 | if (result != ASN1_MEM_ERROR) | ||
1025 | { | ||
1026 | gnutls_assert (); | ||
1027 | result = _gnutls_asn2err (result); | ||
1028 | goto cleanup; | ||
1029 | } | ||
1030 | |||
1031 | /* allocate data for the der | ||
1032 | */ | ||
1033 | |||
1034 | if (str) | ||
1035 | size += 16; /* for later to include the octet tags */ | ||
1036 | asize = size; | ||
1037 | |||
1038 | data = gnutls_malloc (size); | ||
1039 | if (data == NULL) | ||
1040 | { | ||
1041 | gnutls_assert (); | ||
1042 | result = GNUTLS_E_MEMORY_ERROR; | ||
1043 | goto cleanup; | ||
1044 | } | ||
1045 | |||
1046 | result = asn1_der_coding (src, src_name, data, &size, NULL); | ||
1047 | if (result != ASN1_SUCCESS) | ||
1048 | { | ||
1049 | gnutls_assert (); | ||
1050 | result = _gnutls_asn2err (result); | ||
1051 | goto cleanup; | ||
1052 | } | ||
1053 | |||
1054 | if (str) | ||
1055 | { | ||
1056 | if ((result = | ||
1057 | asn1_create_element (_gnutls_get_pkix (), "PKIX1.pkcs-7-Data", | ||
1058 | &c2)) != ASN1_SUCCESS) | ||
1059 | { | ||
1060 | gnutls_assert (); | ||
1061 | result = _gnutls_asn2err (result); | ||
1062 | goto cleanup; | ||
1063 | } | ||
1064 | |||
1065 | result = asn1_write_value (c2, "", data, size); | ||
1066 | if (result != ASN1_SUCCESS) | ||
1067 | { | ||
1068 | gnutls_assert (); | ||
1069 | result = _gnutls_asn2err (result); | ||
1070 | goto cleanup; | ||
1071 | } | ||
1072 | |||
1073 | result = asn1_der_coding (c2, "", data, &asize, NULL); | ||
1074 | if (result != ASN1_SUCCESS) | ||
1075 | { | ||
1076 | gnutls_assert (); | ||
1077 | result = _gnutls_asn2err (result); | ||
1078 | goto cleanup; | ||
1079 | } | ||
1080 | |||
1081 | size = asize; | ||
1082 | |||
1083 | asn1_delete_structure (&c2); | ||
1084 | } | ||
1085 | |||
1086 | res->data = data; | ||
1087 | res->size = size; | ||
1088 | return 0; | ||
1089 | |||
1090 | cleanup:gnutls_free (data); | ||
1091 | asn1_delete_structure (&c2); | ||
1092 | return result; | ||
1093 | |||
1094 | } | ||
1095 | |||
1096 | /* DER Encodes the src ASN1_TYPE and stores it to | ||
1097 | * dest in dest_name. Useful to encode something and store it | ||
1098 | * as OCTET. If str is non null then the data are encoded as | ||
1099 | * an OCTET STRING. | ||
1100 | */ | ||
1101 | int | ||
1102 | _gnutls_x509_der_encode_and_copy (ASN1_TYPE src, | ||
1103 | const char *src_name, | ||
1104 | ASN1_TYPE dest, | ||
1105 | const char *dest_name, int str) | ||
1106 | { | ||
1107 | int result; | ||
1108 | gnutls_datum_t encoded; | ||
1109 | |||
1110 | result = _gnutls_x509_der_encode (src, src_name, &encoded, str); | ||
1111 | |||
1112 | if (result < 0) | ||
1113 | { | ||
1114 | gnutls_assert (); | ||
1115 | return result; | ||
1116 | } | ||
1117 | |||
1118 | /* Write the data. | ||
1119 | */ | ||
1120 | result = asn1_write_value (dest, dest_name, encoded.data, encoded.size); | ||
1121 | |||
1122 | _gnutls_free_datum (&encoded); | ||
1123 | |||
1124 | if (result != ASN1_SUCCESS) | ||
1125 | { | ||
1126 | gnutls_assert (); | ||
1127 | return _gnutls_asn2err (result); | ||
1128 | } | ||
1129 | |||
1130 | return 0; | ||
1131 | } | ||
1132 | |||
1133 | /* Writes the value of the datum in the given ASN1_TYPE. If str is non | ||
1134 | * zero it encodes it as OCTET STRING. | ||
1135 | */ | ||
1136 | int | ||
1137 | _gnutls_x509_write_value (ASN1_TYPE c, | ||
1138 | const char *root, | ||
1139 | const gnutls_datum_t * data, int str) | ||
1140 | { | ||
1141 | int result; | ||
1142 | int asize; | ||
1143 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
1144 | gnutls_datum_t val; | ||
1145 | |||
1146 | asize = data->size + 16; | ||
1147 | |||
1148 | val.data = gnutls_malloc (asize); | ||
1149 | if (val.data == NULL) | ||
1150 | { | ||
1151 | gnutls_assert (); | ||
1152 | result = GNUTLS_E_MEMORY_ERROR; | ||
1153 | goto cleanup; | ||
1154 | } | ||
1155 | |||
1156 | if (str) | ||
1157 | { | ||
1158 | /* Convert it to OCTET STRING | ||
1159 | */ | ||
1160 | if ((result = | ||
1161 | asn1_create_element (_gnutls_get_pkix (), "PKIX1.pkcs-7-Data", | ||
1162 | &c2)) != ASN1_SUCCESS) | ||
1163 | { | ||
1164 | gnutls_assert (); | ||
1165 | result = _gnutls_asn2err (result); | ||
1166 | goto cleanup; | ||
1167 | } | ||
1168 | |||
1169 | result = asn1_write_value (c2, "", data->data, data->size); | ||
1170 | if (result != ASN1_SUCCESS) | ||
1171 | { | ||
1172 | gnutls_assert (); | ||
1173 | result = _gnutls_asn2err (result); | ||
1174 | goto cleanup; | ||
1175 | } | ||
1176 | |||
1177 | result = _gnutls_x509_der_encode (c2, "", &val, 0); | ||
1178 | if (result < 0) | ||
1179 | { | ||
1180 | gnutls_assert (); | ||
1181 | goto cleanup; | ||
1182 | } | ||
1183 | |||
1184 | } | ||
1185 | else | ||
1186 | { | ||
1187 | val.data = data->data; | ||
1188 | val.size = data->size; | ||
1189 | } | ||
1190 | |||
1191 | /* Write the data. | ||
1192 | */ | ||
1193 | result = asn1_write_value (c, root, val.data, val.size); | ||
1194 | |||
1195 | if (val.data != data->data) | ||
1196 | _gnutls_free_datum (&val); | ||
1197 | |||
1198 | if (result != ASN1_SUCCESS) | ||
1199 | { | ||
1200 | gnutls_assert (); | ||
1201 | return _gnutls_asn2err (result); | ||
1202 | } | ||
1203 | |||
1204 | return 0; | ||
1205 | |||
1206 | cleanup:if (val.data != data->data) | ||
1207 | _gnutls_free_datum (&val); | ||
1208 | return result; | ||
1209 | } | ||
1210 | |||
1211 | /* Encodes and copies the private key parameters into a | ||
1212 | * subjectPublicKeyInfo structure. | ||
1213 | * | ||
1214 | */ | ||
1215 | int | ||
1216 | _gnutls_x509_encode_and_copy_PKI_params (ASN1_TYPE dst, | ||
1217 | const char *dst_name, | ||
1218 | gnutls_pk_algorithm_t | ||
1219 | pk_algorithm, | ||
1220 | mpi_t * params, int params_size) | ||
1221 | { | ||
1222 | const char *pk; | ||
1223 | gnutls_datum_t der = { NULL, | ||
1224 | 0 | ||
1225 | }; | ||
1226 | int result; | ||
1227 | char name[128]; | ||
1228 | |||
1229 | pk = _gnutls_x509_pk_to_oid (pk_algorithm); | ||
1230 | if (pk == NULL) | ||
1231 | { | ||
1232 | gnutls_assert (); | ||
1233 | return GNUTLS_E_UNKNOWN_PK_ALGORITHM; | ||
1234 | } | ||
1235 | |||
1236 | /* write the OID | ||
1237 | */ | ||
1238 | _gnutls_str_cpy (name, sizeof (name), dst_name); | ||
1239 | _gnutls_str_cat (name, sizeof (name), ".algorithm.algorithm"); | ||
1240 | result = asn1_write_value (dst, name, pk, 1); | ||
1241 | if (result != ASN1_SUCCESS) | ||
1242 | { | ||
1243 | gnutls_assert (); | ||
1244 | return _gnutls_asn2err (result); | ||
1245 | } | ||
1246 | |||
1247 | if (pk_algorithm == GNUTLS_PK_RSA) | ||
1248 | { | ||
1249 | /* disable parameters, which are not used in RSA. | ||
1250 | */ | ||
1251 | _gnutls_str_cpy (name, sizeof (name), dst_name); | ||
1252 | _gnutls_str_cat (name, sizeof (name), ".algorithm.parameters"); | ||
1253 | result = asn1_write_value (dst, name, NULL, 0); | ||
1254 | if (result != ASN1_SUCCESS) | ||
1255 | { | ||
1256 | gnutls_assert (); | ||
1257 | return _gnutls_asn2err (result); | ||
1258 | } | ||
1259 | |||
1260 | result = _gnutls_x509_write_rsa_params (params, params_size, &der); | ||
1261 | if (result < 0) | ||
1262 | { | ||
1263 | gnutls_assert (); | ||
1264 | return result; | ||
1265 | } | ||
1266 | |||
1267 | /* Write the DER parameters. (in bits) | ||
1268 | */ | ||
1269 | _gnutls_str_cpy (name, sizeof (name), dst_name); | ||
1270 | _gnutls_str_cat (name, sizeof (name), ".subjectPublicKey"); | ||
1271 | result = asn1_write_value (dst, name, der.data, der.size * 8); | ||
1272 | |||
1273 | _gnutls_free_datum (&der); | ||
1274 | |||
1275 | if (result != ASN1_SUCCESS) | ||
1276 | { | ||
1277 | gnutls_assert (); | ||
1278 | return _gnutls_asn2err (result); | ||
1279 | } | ||
1280 | } | ||
1281 | else | ||
1282 | return GNUTLS_E_UNIMPLEMENTED_FEATURE; | ||
1283 | |||
1284 | return 0; | ||
1285 | } | ||
1286 | |||
1287 | /* Reads and returns the PK algorithm of the given certificate-like | ||
1288 | * ASN.1 structure. src_name should be something like "tbsCertificate.subjectPublicKeyInfo". | ||
1289 | */ | ||
1290 | int | ||
1291 | _gnutls_x509_get_pk_algorithm (ASN1_TYPE src, | ||
1292 | const char *src_name, unsigned int *bits) | ||
1293 | { | ||
1294 | int result; | ||
1295 | opaque *str = NULL; | ||
1296 | int algo; | ||
1297 | char oid[64]; | ||
1298 | int len; | ||
1299 | mpi_t params[MAX_PUBLIC_PARAMS_SIZE]; | ||
1300 | char name[128]; | ||
1301 | |||
1302 | _gnutls_str_cpy (name, sizeof (name), src_name); | ||
1303 | _gnutls_str_cat (name, sizeof (name), ".algorithm.algorithm"); | ||
1304 | |||
1305 | len = sizeof (oid); | ||
1306 | result = asn1_read_value (src, name, oid, &len); | ||
1307 | |||
1308 | if (result != ASN1_SUCCESS) | ||
1309 | { | ||
1310 | gnutls_assert (); | ||
1311 | return _gnutls_asn2err (result); | ||
1312 | } | ||
1313 | |||
1314 | algo = _gnutls_x509_oid2pk_algorithm (oid); | ||
1315 | |||
1316 | if (bits == NULL) | ||
1317 | { | ||
1318 | gnutls_free (str); | ||
1319 | return algo; | ||
1320 | } | ||
1321 | |||
1322 | /* Now read the parameters' bits | ||
1323 | */ | ||
1324 | _gnutls_str_cpy (name, sizeof (name), src_name); | ||
1325 | _gnutls_str_cat (name, sizeof (name), ".subjectPublicKey"); | ||
1326 | |||
1327 | len = 0; | ||
1328 | result = asn1_read_value (src, name, NULL, &len); | ||
1329 | if (result != ASN1_MEM_ERROR) | ||
1330 | { | ||
1331 | gnutls_assert (); | ||
1332 | return _gnutls_asn2err (result); | ||
1333 | } | ||
1334 | |||
1335 | if (len % 8 != 0) | ||
1336 | { | ||
1337 | gnutls_assert (); | ||
1338 | return GNUTLS_E_CERTIFICATE_ERROR; | ||
1339 | } | ||
1340 | |||
1341 | len /= 8; | ||
1342 | |||
1343 | str = gnutls_malloc (len); | ||
1344 | if (str == NULL) | ||
1345 | { | ||
1346 | gnutls_assert (); | ||
1347 | return GNUTLS_E_MEMORY_ERROR; | ||
1348 | } | ||
1349 | |||
1350 | _gnutls_str_cpy (name, sizeof (name), src_name); | ||
1351 | _gnutls_str_cat (name, sizeof (name), ".subjectPublicKey"); | ||
1352 | |||
1353 | result = asn1_read_value (src, name, str, &len); | ||
1354 | |||
1355 | if (result != ASN1_SUCCESS) | ||
1356 | { | ||
1357 | gnutls_assert (); | ||
1358 | gnutls_free (str); | ||
1359 | return _gnutls_asn2err (result); | ||
1360 | } | ||
1361 | |||
1362 | len /= 8; | ||
1363 | |||
1364 | switch (algo) | ||
1365 | { | ||
1366 | case GNUTLS_PK_RSA: | ||
1367 | { | ||
1368 | if ((result = _gnutls_x509_read_rsa_params (str, len, params)) < 0) | ||
1369 | { | ||
1370 | gnutls_assert (); | ||
1371 | return result; | ||
1372 | } | ||
1373 | |||
1374 | bits[0] = _gnutls_mpi_get_nbits (params[0]); | ||
1375 | |||
1376 | _gnutls_mpi_release (¶ms[0]); | ||
1377 | _gnutls_mpi_release (¶ms[1]); | ||
1378 | } | ||
1379 | break; | ||
1380 | default: | ||
1381 | _gnutls_x509_log | ||
1382 | ("_gnutls_x509_get_pk_algorithm: unhandled algorithm %d\n", algo); | ||
1383 | } | ||
1384 | |||
1385 | gnutls_free (str); | ||
1386 | return algo; | ||
1387 | } | ||
1388 | |||
1389 | /* Reads the DER signed data from the certificate and allocates space and | ||
1390 | * returns them into signed_data. | ||
1391 | */ | ||
1392 | int | ||
1393 | _gnutls_x509_get_signed_data (ASN1_TYPE src, | ||
1394 | const char *src_name, | ||
1395 | gnutls_datum_t * signed_data) | ||
1396 | { | ||
1397 | gnutls_datum_t der; | ||
1398 | int start, end, result; | ||
1399 | |||
1400 | result = _gnutls_x509_der_encode (src, "", &der, 0); | ||
1401 | if (result < 0) | ||
1402 | { | ||
1403 | gnutls_assert (); | ||
1404 | return result; | ||
1405 | } | ||
1406 | |||
1407 | /* Get the signed data | ||
1408 | */ | ||
1409 | result = asn1_der_decoding_startEnd (src, der.data, der.size, src_name, | ||
1410 | &start, &end); | ||
1411 | if (result != ASN1_SUCCESS) | ||
1412 | { | ||
1413 | result = _gnutls_asn2err (result); | ||
1414 | gnutls_assert (); | ||
1415 | goto cleanup; | ||
1416 | } | ||
1417 | |||
1418 | result = _gnutls_set_datum (signed_data, &der.data[start], end - start + 1); | ||
1419 | |||
1420 | if (result < 0) | ||
1421 | { | ||
1422 | gnutls_assert (); | ||
1423 | goto cleanup; | ||
1424 | } | ||
1425 | |||
1426 | result = 0; | ||
1427 | |||
1428 | cleanup:_gnutls_free_datum (&der); | ||
1429 | |||
1430 | return result; | ||
1431 | } | ||
1432 | |||
1433 | /* Reads the DER signature from the certificate and allocates space and | ||
1434 | * returns them into signed_data. | ||
1435 | */ | ||
1436 | int | ||
1437 | _gnutls_x509_get_signature (ASN1_TYPE src, | ||
1438 | const char *src_name, gnutls_datum_t * signature) | ||
1439 | { | ||
1440 | int bits, result, len; | ||
1441 | |||
1442 | signature->data = NULL; | ||
1443 | signature->size = 0; | ||
1444 | |||
1445 | /* Read the signature | ||
1446 | */ | ||
1447 | bits = 0; | ||
1448 | result = asn1_read_value (src, src_name, NULL, &bits); | ||
1449 | |||
1450 | if (result != ASN1_MEM_ERROR) | ||
1451 | { | ||
1452 | result = _gnutls_asn2err (result); | ||
1453 | gnutls_assert (); | ||
1454 | goto cleanup; | ||
1455 | } | ||
1456 | |||
1457 | if (bits % 8 != 0) | ||
1458 | { | ||
1459 | gnutls_assert (); | ||
1460 | result = GNUTLS_E_CERTIFICATE_ERROR; | ||
1461 | goto cleanup; | ||
1462 | } | ||
1463 | |||
1464 | len = bits / 8; | ||
1465 | |||
1466 | signature->data = gnutls_malloc (len); | ||
1467 | if (signature->data == NULL) | ||
1468 | { | ||
1469 | gnutls_assert (); | ||
1470 | result = GNUTLS_E_MEMORY_ERROR; | ||
1471 | return result; | ||
1472 | } | ||
1473 | |||
1474 | /* read the bit string of the signature | ||
1475 | */ | ||
1476 | bits = len; | ||
1477 | result = asn1_read_value (src, src_name, signature->data, &bits); | ||
1478 | |||
1479 | if (result != ASN1_SUCCESS) | ||
1480 | { | ||
1481 | result = _gnutls_asn2err (result); | ||
1482 | gnutls_assert (); | ||
1483 | goto cleanup; | ||
1484 | } | ||
1485 | |||
1486 | signature->size = len; | ||
1487 | |||
1488 | return 0; | ||
1489 | |||
1490 | cleanup:return result; | ||
1491 | } | ||
diff --git a/src/daemon/https/x509/common.h b/src/daemon/https/x509/common.h new file mode 100644 index 00000000..0b696810 --- /dev/null +++ b/src/daemon/https/x509/common.h | |||
@@ -0,0 +1,126 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef COMMON_H | ||
26 | # define COMMON_H | ||
27 | |||
28 | #include <gnutls.h> | ||
29 | #include <gnutls_algorithms.h> | ||
30 | |||
31 | #define MAX_STRING_LEN 512 | ||
32 | |||
33 | #define GNUTLS_XML_SHOW_ALL 1 | ||
34 | |||
35 | #define PEM_CRL "X509 CRL" | ||
36 | #define PEM_X509_CERT "X509 CERTIFICATE" | ||
37 | #define PEM_X509_CERT2 "CERTIFICATE" | ||
38 | #define PEM_PKCS7 "PKCS7" | ||
39 | #define PEM_PKCS12 "PKCS12" | ||
40 | |||
41 | /* public key algorithm's OIDs | ||
42 | */ | ||
43 | #define PK_PKIX1_RSA_OID "1.2.840.113549.1.1.1" | ||
44 | #define PK_DSA_OID "1.2.840.10040.4.1" | ||
45 | #define PK_GOST_R3410_94_OID "1.2.643.2.2.20" | ||
46 | #define PK_GOST_R3410_2001_OID "1.2.643.2.2.19" | ||
47 | |||
48 | /* signature OIDs | ||
49 | */ | ||
50 | #define SIG_DSA_SHA1_OID "1.2.840.10040.4.3" | ||
51 | #define SIG_RSA_MD5_OID "1.2.840.113549.1.1.4" | ||
52 | #define SIG_RSA_MD2_OID "1.2.840.113549.1.1.2" | ||
53 | #define SIG_RSA_SHA1_OID "1.2.840.113549.1.1.5" | ||
54 | #define SIG_RSA_SHA256_OID "1.2.840.113549.1.1.11" | ||
55 | #define SIG_RSA_SHA384_OID "1.2.840.113549.1.1.12" | ||
56 | #define SIG_RSA_SHA512_OID "1.2.840.113549.1.1.13" | ||
57 | #define SIG_RSA_RMD160_OID "1.3.36.3.3.1.2" | ||
58 | #define SIG_GOST_R3410_94_OID "1.2.643.2.2.4" | ||
59 | #define SIG_GOST_R3410_2001_OID "1.2.643.2.2.3" | ||
60 | |||
61 | time_t _gnutls_x509_utcTime2gtime (const char *ttime); | ||
62 | time_t _gnutls_x509_generalTime2gtime (const char *ttime); | ||
63 | int _gnutls_x509_set_time (ASN1_TYPE c2, const char *where, time_t tim); | ||
64 | |||
65 | int _gnutls_x509_decode_octet_string (const char *string_type, | ||
66 | const opaque * der, size_t der_size, | ||
67 | opaque * output, size_t * output_size); | ||
68 | int _gnutls_x509_oid_data2string (const char *OID, void *value, | ||
69 | int value_size, char *res, | ||
70 | size_t * res_size); | ||
71 | int _gnutls_x509_data2hex (const opaque * data, size_t data_size, | ||
72 | opaque * out, size_t * sizeof_out); | ||
73 | |||
74 | const char *_gnutls_x509_oid2ldap_string (const char *OID); | ||
75 | |||
76 | int _gnutls_x509_oid_data_choice (const char *OID); | ||
77 | int _gnutls_x509_oid_data_printable (const char *OID); | ||
78 | |||
79 | time_t _gnutls_x509_get_time (ASN1_TYPE c2, const char *when); | ||
80 | |||
81 | gnutls_x509_subject_alt_name_t _gnutls_x509_san_find_type (char *str_type); | ||
82 | |||
83 | int _gnutls_x509_der_encode_and_copy (ASN1_TYPE src, const char *src_name, | ||
84 | ASN1_TYPE dest, const char *dest_name, | ||
85 | int str); | ||
86 | int _gnutls_x509_der_encode (ASN1_TYPE src, const char *src_name, | ||
87 | gnutls_datum_t * res, int str); | ||
88 | |||
89 | int _gnutls_x509_export_int (ASN1_TYPE asn1_data, | ||
90 | gnutls_x509_crt_fmt_t format, char *pem_header, | ||
91 | unsigned char *output_data, | ||
92 | size_t * output_data_size); | ||
93 | |||
94 | int _gnutls_x509_read_value (ASN1_TYPE c, const char *root, | ||
95 | gnutls_datum_t * ret, int str); | ||
96 | int _gnutls_x509_write_value (ASN1_TYPE c, const char *root, | ||
97 | const gnutls_datum_t * data, int str); | ||
98 | |||
99 | int _gnutls_x509_encode_and_write_attribute (const char *given_oid, | ||
100 | ASN1_TYPE asn1_struct, | ||
101 | const char *where, | ||
102 | const void *data, | ||
103 | int sizeof_data, int multi); | ||
104 | int _gnutls_x509_decode_and_read_attribute (ASN1_TYPE asn1_struct, | ||
105 | const char *where, char *oid, | ||
106 | int oid_size, | ||
107 | gnutls_datum_t * value, int multi, | ||
108 | int octet); | ||
109 | |||
110 | int _gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const char *src_name, | ||
111 | unsigned int *bits); | ||
112 | |||
113 | int _gnutls_x509_encode_and_copy_PKI_params (ASN1_TYPE dst, | ||
114 | const char *dst_name, | ||
115 | gnutls_pk_algorithm_t | ||
116 | pk_algorithm, mpi_t * params, | ||
117 | int params_size); | ||
118 | int _gnutls_asn1_copy_node (ASN1_TYPE * dst, const char *dst_name, | ||
119 | ASN1_TYPE src, const char *src_name); | ||
120 | |||
121 | int _gnutls_x509_get_signed_data (ASN1_TYPE src, const char *src_name, | ||
122 | gnutls_datum_t * signed_data); | ||
123 | int _gnutls_x509_get_signature (ASN1_TYPE src, const char *src_name, | ||
124 | gnutls_datum_t * signature); | ||
125 | |||
126 | #endif | ||
diff --git a/src/daemon/https/x509/crl.c b/src/daemon/https/x509/crl.c new file mode 100644 index 00000000..d3b5c954 --- /dev/null +++ b/src/daemon/https/x509/crl.c | |||
@@ -0,0 +1,705 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <gnutls_int.h> | ||
26 | #include <libtasn1.h> | ||
27 | |||
28 | #ifdef ENABLE_PKI | ||
29 | |||
30 | #include <gnutls_datum.h> | ||
31 | #include <gnutls_global.h> | ||
32 | #include <gnutls_errors.h> | ||
33 | #include <common.h> | ||
34 | #include <x509_b64.h> | ||
35 | #include <x509.h> | ||
36 | #include <dn.h> | ||
37 | |||
38 | /** | ||
39 | * gnutls_x509_crl_init - This function initializes a gnutls_x509_crl_t structure | ||
40 | * @crl: The structure to be initialized | ||
41 | * | ||
42 | * This function will initialize a CRL structure. CRL stands for | ||
43 | * Certificate Revocation List. A revocation list usually contains | ||
44 | * lists of certificate serial numbers that have been revoked | ||
45 | * by an Authority. The revocation lists are always signed with | ||
46 | * the authority's private key. | ||
47 | * | ||
48 | * Returns 0 on success. | ||
49 | * | ||
50 | **/ | ||
51 | int | ||
52 | gnutls_x509_crl_init (gnutls_x509_crl_t * crl) | ||
53 | { | ||
54 | *crl = gnutls_calloc (1, sizeof (gnutls_x509_crl_int)); | ||
55 | |||
56 | if (*crl) | ||
57 | { | ||
58 | int result = asn1_create_element (_gnutls_get_pkix (), | ||
59 | "PKIX1.CertificateList", | ||
60 | &(*crl)->crl); | ||
61 | if (result != ASN1_SUCCESS) | ||
62 | { | ||
63 | gnutls_assert (); | ||
64 | gnutls_free (*crl); | ||
65 | return _gnutls_asn2err (result); | ||
66 | } | ||
67 | return 0; /* success */ | ||
68 | } | ||
69 | return GNUTLS_E_MEMORY_ERROR; | ||
70 | } | ||
71 | |||
72 | /** | ||
73 | * gnutls_x509_crl_deinit - This function deinitializes memory used by a gnutls_x509_crl_t structure | ||
74 | * @crl: The structure to be initialized | ||
75 | * | ||
76 | * This function will deinitialize a CRL structure. | ||
77 | * | ||
78 | **/ | ||
79 | void | ||
80 | gnutls_x509_crl_deinit (gnutls_x509_crl_t crl) | ||
81 | { | ||
82 | if (!crl) | ||
83 | return; | ||
84 | |||
85 | if (crl->crl) | ||
86 | asn1_delete_structure (&crl->crl); | ||
87 | |||
88 | gnutls_free (crl); | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * gnutls_x509_crl_import - This function will import a DER or PEM encoded CRL | ||
93 | * @crl: The structure to store the parsed CRL. | ||
94 | * @data: The DER or PEM encoded CRL. | ||
95 | * @format: One of DER or PEM | ||
96 | * | ||
97 | * This function will convert the given DER or PEM encoded CRL | ||
98 | * to the native gnutls_x509_crl_t format. The output will be stored in 'crl'. | ||
99 | * | ||
100 | * If the CRL is PEM encoded it should have a header of "X509 CRL". | ||
101 | * | ||
102 | * Returns 0 on success. | ||
103 | * | ||
104 | **/ | ||
105 | int | ||
106 | gnutls_x509_crl_import (gnutls_x509_crl_t crl, | ||
107 | const gnutls_datum_t * data, | ||
108 | gnutls_x509_crt_fmt_t format) | ||
109 | { | ||
110 | int result = 0, need_free = 0; | ||
111 | gnutls_datum_t _data; | ||
112 | |||
113 | _data.data = data->data; | ||
114 | _data.size = data->size; | ||
115 | |||
116 | if (crl == NULL) | ||
117 | { | ||
118 | gnutls_assert (); | ||
119 | return GNUTLS_E_INVALID_REQUEST; | ||
120 | } | ||
121 | |||
122 | /* If the CRL is in PEM format then decode it | ||
123 | */ | ||
124 | if (format == GNUTLS_X509_FMT_PEM) | ||
125 | { | ||
126 | opaque *out; | ||
127 | |||
128 | result = _gnutls_fbase64_decode (PEM_CRL, data->data, data->size, &out); | ||
129 | |||
130 | if (result <= 0) | ||
131 | { | ||
132 | if (result == 0) | ||
133 | result = GNUTLS_E_INTERNAL_ERROR; | ||
134 | gnutls_assert (); | ||
135 | return result; | ||
136 | } | ||
137 | |||
138 | _data.data = out; | ||
139 | _data.size = result; | ||
140 | |||
141 | need_free = 1; | ||
142 | } | ||
143 | |||
144 | |||
145 | result = asn1_der_decoding (&crl->crl, _data.data, _data.size, NULL); | ||
146 | if (result != ASN1_SUCCESS) | ||
147 | { | ||
148 | result = _gnutls_asn2err (result); | ||
149 | gnutls_assert (); | ||
150 | goto cleanup; | ||
151 | } | ||
152 | |||
153 | if (need_free) | ||
154 | _gnutls_free_datum (&_data); | ||
155 | |||
156 | return 0; | ||
157 | |||
158 | cleanup: | ||
159 | if (need_free) | ||
160 | _gnutls_free_datum (&_data); | ||
161 | return result; | ||
162 | } | ||
163 | |||
164 | |||
165 | /** | ||
166 | * gnutls_x509_crl_get_issuer_dn - This function returns the CRL's issuer distinguished name | ||
167 | * @crl: should contain a gnutls_x509_crl_t structure | ||
168 | * @buf: a pointer to a structure to hold the peer's name (may be null) | ||
169 | * @sizeof_buf: initially holds the size of @buf | ||
170 | * | ||
171 | * This function will copy the name of the CRL issuer in the provided buffer. The name | ||
172 | * will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253. The output | ||
173 | * string will be ASCII or UTF-8 encoded, depending on the certificate data. | ||
174 | * | ||
175 | * If buf is null then only the size will be filled. | ||
176 | * | ||
177 | * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not long enough, and | ||
178 | * in that case the sizeof_buf will be updated with the required size, and | ||
179 | * 0 on success. | ||
180 | * | ||
181 | **/ | ||
182 | int | ||
183 | gnutls_x509_crl_get_issuer_dn (const gnutls_x509_crl_t crl, char *buf, | ||
184 | size_t * sizeof_buf) | ||
185 | { | ||
186 | if (crl == NULL) | ||
187 | { | ||
188 | gnutls_assert (); | ||
189 | return GNUTLS_E_INVALID_REQUEST; | ||
190 | } | ||
191 | |||
192 | return _gnutls_x509_parse_dn (crl->crl, | ||
193 | "tbsCertList.issuer.rdnSequence", | ||
194 | buf, sizeof_buf); | ||
195 | } | ||
196 | |||
197 | /** | ||
198 | * gnutls_x509_crl_get_issuer_dn_by_oid - This function returns the CRL's issuer distinguished name | ||
199 | * @crl: should contain a gnutls_x509_crl_t structure | ||
200 | * @oid: holds an Object Identified in null terminated string | ||
201 | * @indx: In case multiple same OIDs exist in the RDN, this specifies which to send. Use zero to get the first one. | ||
202 | * @raw_flag: If non zero returns the raw DER data of the DN part. | ||
203 | * @buf: a pointer to a structure to hold the peer's name (may be null) | ||
204 | * @sizeof_buf: initially holds the size of @buf | ||
205 | * | ||
206 | * This function will extract the part of the name of the CRL issuer specified | ||
207 | * by the given OID. The output will be encoded as described in RFC2253. The output | ||
208 | * string will be ASCII or UTF-8 encoded, depending on the certificate data. | ||
209 | * | ||
210 | * Some helper macros with popular OIDs can be found in gnutls/x509.h | ||
211 | * If raw flag is zero, this function will only return known OIDs as text. Other OIDs | ||
212 | * will be DER encoded, as described in RFC2253 -- in hex format with a '\#' prefix. | ||
213 | * You can check about known OIDs using gnutls_x509_dn_oid_known(). | ||
214 | * | ||
215 | * If buf is null then only the size will be filled. | ||
216 | * | ||
217 | * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not long enough, and | ||
218 | * in that case the sizeof_buf will be updated with the required size, | ||
219 | * and 0 on success. | ||
220 | * | ||
221 | **/ | ||
222 | int | ||
223 | gnutls_x509_crl_get_issuer_dn_by_oid (gnutls_x509_crl_t crl, | ||
224 | const char *oid, int indx, | ||
225 | unsigned int raw_flag, void *buf, | ||
226 | size_t * sizeof_buf) | ||
227 | { | ||
228 | if (crl == NULL) | ||
229 | { | ||
230 | gnutls_assert (); | ||
231 | return GNUTLS_E_INVALID_REQUEST; | ||
232 | } | ||
233 | |||
234 | return _gnutls_x509_parse_dn_oid (crl->crl, | ||
235 | "tbsCertList.issuer.rdnSequence", | ||
236 | oid, indx, raw_flag, buf, sizeof_buf); | ||
237 | } | ||
238 | |||
239 | /** | ||
240 | * gnutls_x509_crl_get_dn_oid - This function returns the Certificate request issuer's distinguished name OIDs | ||
241 | * @crl: should contain a gnutls_x509_crl_t structure | ||
242 | * @indx: Specifies which DN OID to send. Use zero to get the first one. | ||
243 | * @oid: a pointer to a structure to hold the name (may be null) | ||
244 | * @sizeof_oid: initially holds the size of 'oid' | ||
245 | * | ||
246 | * This function will extract the requested OID of the name of the CRL issuer, specified | ||
247 | * by the given index. | ||
248 | * | ||
249 | * If oid is null then only the size will be filled. | ||
250 | * | ||
251 | * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not long enough, and | ||
252 | * in that case the sizeof_oid will be updated with the required size. | ||
253 | * On success 0 is returned. | ||
254 | * | ||
255 | **/ | ||
256 | int | ||
257 | gnutls_x509_crl_get_dn_oid (gnutls_x509_crl_t crl, | ||
258 | int indx, void *oid, size_t * sizeof_oid) | ||
259 | { | ||
260 | if (crl == NULL) | ||
261 | { | ||
262 | gnutls_assert (); | ||
263 | return GNUTLS_E_INVALID_REQUEST; | ||
264 | } | ||
265 | |||
266 | return _gnutls_x509_get_dn_oid (crl->crl, | ||
267 | "tbsCertList.issuer.rdnSequence", indx, | ||
268 | oid, sizeof_oid); | ||
269 | } | ||
270 | |||
271 | |||
272 | /** | ||
273 | * gnutls_x509_crl_get_signature_algorithm - This function returns the CRL's signature algorithm | ||
274 | * @crl: should contain a gnutls_x509_crl_t structure | ||
275 | * | ||
276 | * This function will return a value of the gnutls_sign_algorithm_t enumeration that | ||
277 | * is the signature algorithm. | ||
278 | * | ||
279 | * Returns a negative value on error. | ||
280 | * | ||
281 | **/ | ||
282 | int | ||
283 | gnutls_x509_crl_get_signature_algorithm (gnutls_x509_crl_t crl) | ||
284 | { | ||
285 | int result; | ||
286 | gnutls_datum_t sa; | ||
287 | |||
288 | if (crl == NULL) | ||
289 | { | ||
290 | gnutls_assert (); | ||
291 | return GNUTLS_E_INVALID_REQUEST; | ||
292 | } | ||
293 | |||
294 | /* Read the signature algorithm. Note that parameters are not | ||
295 | * read. They will be read from the issuer's certificate if needed. | ||
296 | */ | ||
297 | |||
298 | result = | ||
299 | _gnutls_x509_read_value (crl->crl, "signatureAlgorithm.algorithm", | ||
300 | &sa, 0); | ||
301 | |||
302 | if (result < 0) | ||
303 | { | ||
304 | gnutls_assert (); | ||
305 | return result; | ||
306 | } | ||
307 | |||
308 | result = _gnutls_x509_oid2sign_algorithm ((const char *) sa.data); | ||
309 | |||
310 | _gnutls_free_datum (&sa); | ||
311 | |||
312 | return result; | ||
313 | } | ||
314 | |||
315 | /** | ||
316 | * gnutls_x509_crl_get_signature - Returns the CRL's signature | ||
317 | * @crl: should contain a gnutls_x509_crl_t structure | ||
318 | * @sig: a pointer where the signature part will be copied (may be null). | ||
319 | * @sizeof_sig: initially holds the size of @sig | ||
320 | * | ||
321 | * This function will extract the signature field of a CRL. | ||
322 | * | ||
323 | * Returns 0 on success, and a negative value on error. | ||
324 | **/ | ||
325 | int | ||
326 | gnutls_x509_crl_get_signature (gnutls_x509_crl_t crl, | ||
327 | char *sig, size_t * sizeof_sig) | ||
328 | { | ||
329 | int result; | ||
330 | int bits, len; | ||
331 | |||
332 | if (crl == NULL) | ||
333 | { | ||
334 | gnutls_assert (); | ||
335 | return GNUTLS_E_INVALID_REQUEST; | ||
336 | } | ||
337 | |||
338 | bits = 0; | ||
339 | result = asn1_read_value (crl->crl, "signature", NULL, &bits); | ||
340 | if (result != ASN1_MEM_ERROR) | ||
341 | { | ||
342 | gnutls_assert (); | ||
343 | return _gnutls_asn2err (result); | ||
344 | } | ||
345 | |||
346 | if (bits % 8 != 0) | ||
347 | { | ||
348 | gnutls_assert (); | ||
349 | return GNUTLS_E_CERTIFICATE_ERROR; | ||
350 | } | ||
351 | |||
352 | len = bits / 8; | ||
353 | |||
354 | if (*sizeof_sig < len) | ||
355 | { | ||
356 | *sizeof_sig = bits / 8; | ||
357 | return GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
358 | } | ||
359 | |||
360 | result = asn1_read_value (crl->crl, "signature", sig, &len); | ||
361 | if (result != ASN1_SUCCESS) | ||
362 | { | ||
363 | gnutls_assert (); | ||
364 | return _gnutls_asn2err (result); | ||
365 | } | ||
366 | |||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | /** | ||
371 | * gnutls_x509_crl_get_version - This function returns the CRL's version number | ||
372 | * @crl: should contain a gnutls_x509_crl_t structure | ||
373 | * | ||
374 | * This function will return the version of the specified CRL. | ||
375 | * | ||
376 | * Returns a negative value on error. | ||
377 | * | ||
378 | **/ | ||
379 | int | ||
380 | gnutls_x509_crl_get_version (gnutls_x509_crl_t crl) | ||
381 | { | ||
382 | opaque version[5]; | ||
383 | int len, result; | ||
384 | |||
385 | if (crl == NULL) | ||
386 | { | ||
387 | gnutls_assert (); | ||
388 | return GNUTLS_E_INVALID_REQUEST; | ||
389 | } | ||
390 | |||
391 | len = sizeof (version); | ||
392 | if ((result = | ||
393 | asn1_read_value (crl->crl, "tbsCertList.version", version, | ||
394 | &len)) != ASN1_SUCCESS) | ||
395 | { | ||
396 | gnutls_assert (); | ||
397 | return _gnutls_asn2err (result); | ||
398 | } | ||
399 | |||
400 | return (int) version[0] + 1; | ||
401 | } | ||
402 | |||
403 | /** | ||
404 | * gnutls_x509_crl_get_this_update - This function returns the CRL's thisUpdate time | ||
405 | * @crl: should contain a gnutls_x509_crl_t structure | ||
406 | * | ||
407 | * This function will return the time this CRL was issued. | ||
408 | * | ||
409 | * Returns (time_t)-1 on error. | ||
410 | * | ||
411 | **/ | ||
412 | time_t | ||
413 | gnutls_x509_crl_get_this_update (gnutls_x509_crl_t crl) | ||
414 | { | ||
415 | if (crl == NULL) | ||
416 | { | ||
417 | gnutls_assert (); | ||
418 | return (time_t) - 1; | ||
419 | } | ||
420 | |||
421 | return _gnutls_x509_get_time (crl->crl, "tbsCertList.thisUpdate"); | ||
422 | } | ||
423 | |||
424 | /** | ||
425 | * gnutls_x509_crl_get_next_update - This function returns the CRL's nextUpdate time | ||
426 | * @crl: should contain a gnutls_x509_crl_t structure | ||
427 | * | ||
428 | * This function will return the time the next CRL will be issued. | ||
429 | * This field is optional in a CRL so it might be normal to get | ||
430 | * an error instead. | ||
431 | * | ||
432 | * Returns (time_t)-1 on error. | ||
433 | * | ||
434 | **/ | ||
435 | time_t | ||
436 | gnutls_x509_crl_get_next_update (gnutls_x509_crl_t crl) | ||
437 | { | ||
438 | if (crl == NULL) | ||
439 | { | ||
440 | gnutls_assert (); | ||
441 | return (time_t) - 1; | ||
442 | } | ||
443 | |||
444 | return _gnutls_x509_get_time (crl->crl, "tbsCertList.nextUpdate"); | ||
445 | } | ||
446 | |||
447 | /** | ||
448 | * gnutls_x509_crl_get_crt_count - This function returns the number of revoked certificates in a CRL | ||
449 | * @crl: should contain a gnutls_x509_crl_t structure | ||
450 | * | ||
451 | * This function will return the number of revoked certificates in the | ||
452 | * given CRL. | ||
453 | * | ||
454 | * Returns a negative value on failure. | ||
455 | * | ||
456 | **/ | ||
457 | int | ||
458 | gnutls_x509_crl_get_crt_count (gnutls_x509_crl_t crl) | ||
459 | { | ||
460 | |||
461 | int count, result; | ||
462 | |||
463 | if (crl == NULL) | ||
464 | { | ||
465 | gnutls_assert (); | ||
466 | return GNUTLS_E_INVALID_REQUEST; | ||
467 | } | ||
468 | |||
469 | result = | ||
470 | asn1_number_of_elements (crl->crl, | ||
471 | "tbsCertList.revokedCertificates", &count); | ||
472 | |||
473 | if (result != ASN1_SUCCESS) | ||
474 | { | ||
475 | gnutls_assert (); | ||
476 | return 0; /* no certificates */ | ||
477 | } | ||
478 | |||
479 | return count; | ||
480 | } | ||
481 | |||
482 | /** | ||
483 | * gnutls_x509_crl_get_crt_serial - This function returns the serial number of a revoked certificate | ||
484 | * @crl: should contain a gnutls_x509_crl_t structure | ||
485 | * @indx: the index of the certificate to extract (starting from 0) | ||
486 | * @serial: where the serial number will be copied | ||
487 | * @serial_size: initially holds the size of serial | ||
488 | * @t: if non null, will hold the time this certificate was revoked | ||
489 | * | ||
490 | * This function will return the serial number of the specified, by | ||
491 | * the index, revoked certificate. | ||
492 | * | ||
493 | * Returns a negative value on failure. | ||
494 | * | ||
495 | **/ | ||
496 | int | ||
497 | gnutls_x509_crl_get_crt_serial (gnutls_x509_crl_t crl, int indx, | ||
498 | unsigned char *serial, | ||
499 | size_t * serial_size, time_t * t) | ||
500 | { | ||
501 | |||
502 | int result, _serial_size; | ||
503 | char serial_name[MAX_NAME_SIZE]; | ||
504 | char date_name[MAX_NAME_SIZE]; | ||
505 | |||
506 | if (crl == NULL) | ||
507 | { | ||
508 | gnutls_assert (); | ||
509 | return GNUTLS_E_INVALID_REQUEST; | ||
510 | } | ||
511 | |||
512 | snprintf (serial_name, sizeof (serial_name), | ||
513 | "tbsCertList.revokedCertificates.?%u.userCertificate", indx + 1); | ||
514 | snprintf (date_name, sizeof (date_name), | ||
515 | "tbsCertList.revokedCertificates.?%u.revocationDate", indx + 1); | ||
516 | |||
517 | _serial_size = *serial_size; | ||
518 | result = asn1_read_value (crl->crl, serial_name, serial, &_serial_size); | ||
519 | |||
520 | *serial_size = _serial_size; | ||
521 | if (result != ASN1_SUCCESS) | ||
522 | { | ||
523 | gnutls_assert (); | ||
524 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
525 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
526 | return _gnutls_asn2err (result); | ||
527 | } | ||
528 | |||
529 | if (t) | ||
530 | { | ||
531 | *t = _gnutls_x509_get_time (crl->crl, date_name); | ||
532 | } | ||
533 | |||
534 | return 0; | ||
535 | } | ||
536 | |||
537 | /*- | ||
538 | * _gnutls_x509_crl_get_raw_issuer_dn - This function returns the issuer's DN DER encoded | ||
539 | * @crl: should contain a gnutls_x509_crl_t structure | ||
540 | * @dn: will hold the starting point of the DN | ||
541 | * | ||
542 | * This function will return a pointer to the DER encoded DN structure and | ||
543 | * the length. | ||
544 | * | ||
545 | * Returns a negative value on error, and zero on success. | ||
546 | * | ||
547 | -*/ | ||
548 | int | ||
549 | _gnutls_x509_crl_get_raw_issuer_dn (gnutls_x509_crl_t crl, | ||
550 | gnutls_datum_t * dn) | ||
551 | { | ||
552 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
553 | int result, len1; | ||
554 | int start1, end1; | ||
555 | gnutls_datum_t crl_signed_data; | ||
556 | |||
557 | if (crl == NULL) | ||
558 | { | ||
559 | gnutls_assert (); | ||
560 | return GNUTLS_E_INVALID_REQUEST; | ||
561 | } | ||
562 | |||
563 | /* get the issuer of 'crl' | ||
564 | */ | ||
565 | if ((result = | ||
566 | asn1_create_element (_gnutls_get_pkix (), "PKIX1.TBSCertList", | ||
567 | &c2)) != ASN1_SUCCESS) | ||
568 | { | ||
569 | gnutls_assert (); | ||
570 | return _gnutls_asn2err (result); | ||
571 | } | ||
572 | |||
573 | result = | ||
574 | _gnutls_x509_get_signed_data (crl->crl, "tbsCertList", &crl_signed_data); | ||
575 | if (result < 0) | ||
576 | { | ||
577 | gnutls_assert (); | ||
578 | goto cleanup; | ||
579 | } | ||
580 | |||
581 | result = | ||
582 | asn1_der_decoding (&c2, crl_signed_data.data, crl_signed_data.size, NULL); | ||
583 | if (result != ASN1_SUCCESS) | ||
584 | { | ||
585 | /* couldn't decode DER */ | ||
586 | gnutls_assert (); | ||
587 | asn1_delete_structure (&c2); | ||
588 | result = _gnutls_asn2err (result); | ||
589 | goto cleanup; | ||
590 | } | ||
591 | |||
592 | result = | ||
593 | asn1_der_decoding_startEnd (c2, crl_signed_data.data, | ||
594 | crl_signed_data.size, "issuer", | ||
595 | &start1, &end1); | ||
596 | |||
597 | if (result != ASN1_SUCCESS) | ||
598 | { | ||
599 | gnutls_assert (); | ||
600 | result = _gnutls_asn2err (result); | ||
601 | goto cleanup; | ||
602 | } | ||
603 | |||
604 | len1 = end1 - start1 + 1; | ||
605 | |||
606 | _gnutls_set_datum (dn, &crl_signed_data.data[start1], len1); | ||
607 | |||
608 | result = 0; | ||
609 | |||
610 | cleanup: | ||
611 | asn1_delete_structure (&c2); | ||
612 | _gnutls_free_datum (&crl_signed_data); | ||
613 | return result; | ||
614 | } | ||
615 | |||
616 | /** | ||
617 | * gnutls_x509_crl_export - This function will export the CRL | ||
618 | * @crl: Holds the revocation list | ||
619 | * @format: the format of output params. One of PEM or DER. | ||
620 | * @output_data: will contain a private key PEM or DER encoded | ||
621 | * @output_data_size: holds the size of output_data (and will be replaced by the actual size of parameters) | ||
622 | * | ||
623 | * This function will export the revocation list to DER or PEM format. | ||
624 | * | ||
625 | * If the buffer provided is not long enough to hold the output, then | ||
626 | * GNUTLS_E_SHORT_MEMORY_BUFFER will be returned. | ||
627 | * | ||
628 | * If the structure is PEM encoded, it will have a header | ||
629 | * of "BEGIN X509 CRL". | ||
630 | * | ||
631 | * Returns 0 on success, and a negative value on failure. | ||
632 | * | ||
633 | **/ | ||
634 | int | ||
635 | gnutls_x509_crl_export (gnutls_x509_crl_t crl, | ||
636 | gnutls_x509_crt_fmt_t format, void *output_data, | ||
637 | size_t * output_data_size) | ||
638 | { | ||
639 | if (crl == NULL) | ||
640 | { | ||
641 | gnutls_assert (); | ||
642 | return GNUTLS_E_INVALID_REQUEST; | ||
643 | } | ||
644 | |||
645 | return _gnutls_x509_export_int (crl->crl, format, PEM_CRL, | ||
646 | output_data, output_data_size); | ||
647 | } | ||
648 | |||
649 | /*- | ||
650 | * _gnutls_x509_crl_cpy - This function copies a gnutls_x509_crl_t structure | ||
651 | * @dest: The structure where to copy | ||
652 | * @src: The structure to be copied | ||
653 | * | ||
654 | * This function will copy an X.509 certificate structure. | ||
655 | * | ||
656 | * Returns 0 on success. | ||
657 | * | ||
658 | -*/ | ||
659 | int | ||
660 | _gnutls_x509_crl_cpy (gnutls_x509_crl_t dest, gnutls_x509_crl_t src) | ||
661 | { | ||
662 | int ret; | ||
663 | size_t der_size; | ||
664 | opaque *der; | ||
665 | gnutls_datum_t tmp; | ||
666 | |||
667 | ret = gnutls_x509_crl_export (src, GNUTLS_X509_FMT_DER, NULL, &der_size); | ||
668 | if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) | ||
669 | { | ||
670 | gnutls_assert (); | ||
671 | return ret; | ||
672 | } | ||
673 | |||
674 | der = gnutls_alloca (der_size); | ||
675 | if (der == NULL) | ||
676 | { | ||
677 | gnutls_assert (); | ||
678 | return GNUTLS_E_MEMORY_ERROR; | ||
679 | } | ||
680 | |||
681 | ret = gnutls_x509_crl_export (src, GNUTLS_X509_FMT_DER, der, &der_size); | ||
682 | if (ret < 0) | ||
683 | { | ||
684 | gnutls_assert (); | ||
685 | gnutls_afree (der); | ||
686 | return ret; | ||
687 | } | ||
688 | |||
689 | tmp.data = der; | ||
690 | tmp.size = der_size; | ||
691 | ret = gnutls_x509_crl_import (dest, &tmp, GNUTLS_X509_FMT_DER); | ||
692 | |||
693 | gnutls_afree (der); | ||
694 | |||
695 | if (ret < 0) | ||
696 | { | ||
697 | gnutls_assert (); | ||
698 | return ret; | ||
699 | } | ||
700 | |||
701 | return 0; | ||
702 | |||
703 | } | ||
704 | |||
705 | #endif | ||
diff --git a/src/daemon/https/x509/crl_write.c b/src/daemon/https/x509/crl_write.c new file mode 100644 index 00000000..370a492c --- /dev/null +++ b/src/daemon/https/x509/crl_write.c | |||
@@ -0,0 +1,316 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | /* This file contains functions to handle CRL generation. | ||
26 | */ | ||
27 | |||
28 | #include <gnutls_int.h> | ||
29 | |||
30 | #ifdef ENABLE_PKI | ||
31 | |||
32 | #include <gnutls_datum.h> | ||
33 | #include <gnutls_global.h> | ||
34 | #include <gnutls_errors.h> | ||
35 | #include <common.h> | ||
36 | #include <gnutls_x509.h> | ||
37 | #include <x509_b64.h> | ||
38 | #include <crq.h> | ||
39 | #include <dn.h> | ||
40 | #include <mpi.h> | ||
41 | #include <sign.h> | ||
42 | #include <extensions.h> | ||
43 | #include <libtasn1.h> | ||
44 | |||
45 | static void disable_optional_stuff (gnutls_x509_crl_t crl); | ||
46 | |||
47 | /** | ||
48 | * gnutls_x509_crl_set_version - This function will set the CRL version | ||
49 | * @crl: should contain a gnutls_x509_crl_t structure | ||
50 | * @version: holds the version number. For CRLv1 crls must be 1. | ||
51 | * | ||
52 | * This function will set the version of the CRL. This | ||
53 | * must be one for CRL version 1, and so on. The CRLs generated | ||
54 | * by gnutls should have a version number of 2. | ||
55 | * | ||
56 | * Returns 0 on success. | ||
57 | * | ||
58 | **/ | ||
59 | int | ||
60 | gnutls_x509_crl_set_version (gnutls_x509_crl_t crl, unsigned int version) | ||
61 | { | ||
62 | int result; | ||
63 | char null = version; | ||
64 | |||
65 | if (crl == NULL) | ||
66 | { | ||
67 | gnutls_assert (); | ||
68 | return GNUTLS_E_INVALID_REQUEST; | ||
69 | } | ||
70 | |||
71 | null -= 1; | ||
72 | if (null < 0) | ||
73 | null = 0; | ||
74 | |||
75 | result = asn1_write_value (crl->crl, "tbsCertList.version", &null, 1); | ||
76 | if (result != ASN1_SUCCESS) | ||
77 | { | ||
78 | gnutls_assert (); | ||
79 | return _gnutls_asn2err (result); | ||
80 | } | ||
81 | |||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | /** | ||
86 | * gnutls_x509_crl_sign2 - This function will sign a CRL with a key | ||
87 | * @crl: should contain a gnutls_x509_crl_t structure | ||
88 | * @issuer: is the certificate of the certificate issuer | ||
89 | * @issuer_key: holds the issuer's private key | ||
90 | * @dig: The message digest to use. GNUTLS_DIG_SHA1 is the safe choice unless you know what you're doing. | ||
91 | * @flags: must be 0 | ||
92 | * | ||
93 | * This function will sign the CRL with the issuer's private key, and | ||
94 | * will copy the issuer's information into the CRL. | ||
95 | * | ||
96 | * This must be the last step in a certificate CRL since all | ||
97 | * the previously set parameters are now signed. | ||
98 | * | ||
99 | * Returns 0 on success. | ||
100 | * | ||
101 | **/ | ||
102 | int | ||
103 | gnutls_x509_crl_sign2 (gnutls_x509_crl_t crl, gnutls_x509_crt_t issuer, | ||
104 | gnutls_x509_privkey_t issuer_key, | ||
105 | gnutls_digest_algorithm_t dig, unsigned int flags) | ||
106 | { | ||
107 | int result; | ||
108 | |||
109 | if (crl == NULL || issuer == NULL) | ||
110 | { | ||
111 | gnutls_assert (); | ||
112 | return GNUTLS_E_INVALID_REQUEST; | ||
113 | } | ||
114 | |||
115 | /* disable all the unneeded OPTIONAL fields. | ||
116 | */ | ||
117 | disable_optional_stuff (crl); | ||
118 | |||
119 | result = _gnutls_x509_pkix_sign (crl->crl, "tbsCertList", | ||
120 | dig, issuer, issuer_key); | ||
121 | if (result < 0) | ||
122 | { | ||
123 | gnutls_assert (); | ||
124 | return result; | ||
125 | } | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * gnutls_x509_crl_sign - This function will sign a CRL with a key | ||
132 | * @crl: should contain a gnutls_x509_crl_t structure | ||
133 | * @issuer: is the certificate of the certificate issuer | ||
134 | * @issuer_key: holds the issuer's private key | ||
135 | * | ||
136 | * This function is the same a gnutls_x509_crl_sign2() with no flags, and | ||
137 | * SHA1 as the hash algorithm. | ||
138 | * | ||
139 | * Returns 0 on success. | ||
140 | * | ||
141 | **/ | ||
142 | int | ||
143 | gnutls_x509_crl_sign (gnutls_x509_crl_t crl, gnutls_x509_crt_t issuer, | ||
144 | gnutls_x509_privkey_t issuer_key) | ||
145 | { | ||
146 | return gnutls_x509_crl_sign2 (crl, issuer, issuer_key, GNUTLS_DIG_SHA1, 0); | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * gnutls_x509_crl_set_this_update - This function will set the CRL's issuing time | ||
151 | * @crl: should contain a gnutls_x509_crl_t structure | ||
152 | * @act_time: The actual time | ||
153 | * | ||
154 | * This function will set the time this CRL was issued. | ||
155 | * | ||
156 | * Returns 0 on success, or a negative value in case of an error. | ||
157 | * | ||
158 | **/ | ||
159 | int | ||
160 | gnutls_x509_crl_set_this_update (gnutls_x509_crl_t crl, time_t act_time) | ||
161 | { | ||
162 | if (crl == NULL) | ||
163 | { | ||
164 | gnutls_assert (); | ||
165 | return GNUTLS_E_INVALID_REQUEST; | ||
166 | } | ||
167 | |||
168 | return _gnutls_x509_set_time (crl->crl, "tbsCertList.thisUpdate", act_time); | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * gnutls_x509_crl_set_next_update - This function will set the CRL next update time | ||
173 | * @crl: should contain a gnutls_x509_crl_t structure | ||
174 | * @exp_time: The actual time | ||
175 | * | ||
176 | * This function will set the time this CRL will be updated. | ||
177 | * | ||
178 | * Returns 0 on success, or a negative value in case of an error. | ||
179 | * | ||
180 | **/ | ||
181 | int | ||
182 | gnutls_x509_crl_set_next_update (gnutls_x509_crl_t crl, time_t exp_time) | ||
183 | { | ||
184 | if (crl == NULL) | ||
185 | { | ||
186 | gnutls_assert (); | ||
187 | return GNUTLS_E_INVALID_REQUEST; | ||
188 | } | ||
189 | return _gnutls_x509_set_time (crl->crl, "tbsCertList.nextUpdate", exp_time); | ||
190 | } | ||
191 | |||
192 | /** | ||
193 | * gnutls_x509_crl_set_crt_serial - This function will set a revoked certificate's serial number | ||
194 | * @crl: should contain a gnutls_x509_crl_t structure | ||
195 | * @serial: The revoked certificate's serial number | ||
196 | * @serial_size: Holds the size of the serial field. | ||
197 | * @revocation_time: The time this certificate was revoked | ||
198 | * | ||
199 | * This function will set a revoked certificate's serial number to the CRL. | ||
200 | * | ||
201 | * Returns 0 on success, or a negative value in case of an error. | ||
202 | * | ||
203 | **/ | ||
204 | int | ||
205 | gnutls_x509_crl_set_crt_serial (gnutls_x509_crl_t crl, | ||
206 | const void *serial, size_t serial_size, | ||
207 | time_t revocation_time) | ||
208 | { | ||
209 | int ret; | ||
210 | |||
211 | if (crl == NULL) | ||
212 | { | ||
213 | gnutls_assert (); | ||
214 | return GNUTLS_E_INVALID_REQUEST; | ||
215 | } | ||
216 | |||
217 | ret = | ||
218 | asn1_write_value (crl->crl, "tbsCertList.revokedCertificates", "NEW", 1); | ||
219 | if (ret != ASN1_SUCCESS) | ||
220 | { | ||
221 | gnutls_assert (); | ||
222 | return _gnutls_asn2err (ret); | ||
223 | } | ||
224 | |||
225 | ret = | ||
226 | asn1_write_value (crl->crl, | ||
227 | "tbsCertList.revokedCertificates.?LAST.userCertificate", | ||
228 | serial, serial_size); | ||
229 | if (ret != ASN1_SUCCESS) | ||
230 | { | ||
231 | gnutls_assert (); | ||
232 | return _gnutls_asn2err (ret); | ||
233 | } | ||
234 | |||
235 | ret = | ||
236 | _gnutls_x509_set_time (crl->crl, | ||
237 | "tbsCertList.revokedCertificates.?LAST.revocationDate", | ||
238 | revocation_time); | ||
239 | if (ret < 0) | ||
240 | { | ||
241 | gnutls_assert (); | ||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | ret = | ||
246 | asn1_write_value (crl->crl, | ||
247 | "tbsCertList.revokedCertificates.?LAST.crlEntryExtensions", | ||
248 | NULL, 0); | ||
249 | if (ret != ASN1_SUCCESS) | ||
250 | { | ||
251 | gnutls_assert (); | ||
252 | return _gnutls_asn2err (ret); | ||
253 | } | ||
254 | |||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | /** | ||
259 | * gnutls_x509_crl_set_crt - This function will set a revoked certificate's serial number | ||
260 | * @crl: should contain a gnutls_x509_crl_t structure | ||
261 | * @crt: should contain a gnutls_x509_crt_t structure with the revoked certificate | ||
262 | * @revocation_time: The time this certificate was revoked | ||
263 | * | ||
264 | * This function will set a revoked certificate's serial number to the CRL. | ||
265 | * | ||
266 | * Returns 0 on success, or a negative value in case of an error. | ||
267 | * | ||
268 | **/ | ||
269 | int | ||
270 | gnutls_x509_crl_set_crt (gnutls_x509_crl_t crl, gnutls_x509_crt_t crt, | ||
271 | time_t revocation_time) | ||
272 | { | ||
273 | int ret; | ||
274 | opaque serial[128]; | ||
275 | size_t serial_size; | ||
276 | |||
277 | if (crl == NULL || crt == NULL) | ||
278 | { | ||
279 | gnutls_assert (); | ||
280 | return GNUTLS_E_INVALID_REQUEST; | ||
281 | } | ||
282 | |||
283 | serial_size = sizeof (serial); | ||
284 | ret = gnutls_x509_crt_get_serial (crt, serial, &serial_size); | ||
285 | if (ret < 0) | ||
286 | { | ||
287 | gnutls_assert (); | ||
288 | return ret; | ||
289 | } | ||
290 | |||
291 | ret = | ||
292 | gnutls_x509_crl_set_crt_serial (crl, serial, serial_size, | ||
293 | revocation_time); | ||
294 | if (ret < 0) | ||
295 | { | ||
296 | gnutls_assert (); | ||
297 | return _gnutls_asn2err (ret); | ||
298 | } | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | |||
304 | /* If OPTIONAL fields have not been initialized then | ||
305 | * disable them. | ||
306 | */ | ||
307 | static void | ||
308 | disable_optional_stuff (gnutls_x509_crl_t crl) | ||
309 | { | ||
310 | |||
311 | asn1_write_value (crl->crl, "tbsCertList.crlExtensions", NULL, 0); | ||
312 | |||
313 | return; | ||
314 | } | ||
315 | |||
316 | #endif /* ENABLE_PKI */ | ||
diff --git a/src/daemon/https/x509/crq.c b/src/daemon/https/x509/crq.c new file mode 100644 index 00000000..8e663d51 --- /dev/null +++ b/src/daemon/https/x509/crq.c | |||
@@ -0,0 +1,887 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | /* This file contains functions to handle PKCS #10 certificate requests. | ||
26 | */ | ||
27 | |||
28 | #include <gnutls_int.h> | ||
29 | |||
30 | #ifdef ENABLE_PKI | ||
31 | |||
32 | #include <gnutls_datum.h> | ||
33 | #include <gnutls_global.h> | ||
34 | #include <gnutls_errors.h> | ||
35 | #include <common.h> | ||
36 | #include <gnutls_x509.h> | ||
37 | #include <x509_b64.h> | ||
38 | #include <crq.h> | ||
39 | #include <dn.h> | ||
40 | #include <mpi.h> | ||
41 | #include <sign.h> | ||
42 | #include <extensions.h> | ||
43 | #include <libtasn1.h> | ||
44 | |||
45 | /** | ||
46 | * gnutls_x509_crq_init - This function initializes a gnutls_x509_crq_t structure | ||
47 | * @crq: The structure to be initialized | ||
48 | * | ||
49 | * This function will initialize a PKCS10 certificate request structure. | ||
50 | * | ||
51 | * Returns 0 on success. | ||
52 | * | ||
53 | **/ | ||
54 | int | ||
55 | gnutls_x509_crq_init (gnutls_x509_crq_t * crq) | ||
56 | { | ||
57 | *crq = gnutls_calloc (1, sizeof (gnutls_x509_crq_int)); | ||
58 | |||
59 | if (*crq) | ||
60 | { | ||
61 | int result = asn1_create_element (_gnutls_get_pkix (), | ||
62 | "PKIX1.pkcs-10-CertificationRequest", | ||
63 | &((*crq)->crq)); | ||
64 | if (result != ASN1_SUCCESS) | ||
65 | { | ||
66 | gnutls_assert (); | ||
67 | gnutls_free (*crq); | ||
68 | return _gnutls_asn2err (result); | ||
69 | } | ||
70 | return 0; /* success */ | ||
71 | } | ||
72 | return GNUTLS_E_MEMORY_ERROR; | ||
73 | } | ||
74 | |||
75 | /** | ||
76 | * gnutls_x509_crq_deinit - This function deinitializes memory used by a gnutls_x509_crq_t structure | ||
77 | * @crq: The structure to be initialized | ||
78 | * | ||
79 | * This function will deinitialize a CRL structure. | ||
80 | * | ||
81 | **/ | ||
82 | void | ||
83 | gnutls_x509_crq_deinit (gnutls_x509_crq_t crq) | ||
84 | { | ||
85 | if (!crq) | ||
86 | return; | ||
87 | |||
88 | if (crq->crq) | ||
89 | asn1_delete_structure (&crq->crq); | ||
90 | |||
91 | gnutls_free (crq); | ||
92 | } | ||
93 | |||
94 | #define PEM_CRQ "NEW CERTIFICATE REQUEST" | ||
95 | #define PEM_CRQ2 "CERTIFICATE REQUEST" | ||
96 | |||
97 | /** | ||
98 | * gnutls_x509_crq_import - This function will import a DER or PEM encoded Certificate request | ||
99 | * @crq: The structure to store the parsed certificate request. | ||
100 | * @data: The DER or PEM encoded certificate. | ||
101 | * @format: One of DER or PEM | ||
102 | * | ||
103 | * This function will convert the given DER or PEM encoded Certificate | ||
104 | * to the native gnutls_x509_crq_t format. The output will be stored in @cert. | ||
105 | * | ||
106 | * If the Certificate is PEM encoded it should have a header of "NEW CERTIFICATE REQUEST". | ||
107 | * | ||
108 | * Returns 0 on success. | ||
109 | * | ||
110 | **/ | ||
111 | int | ||
112 | gnutls_x509_crq_import (gnutls_x509_crq_t crq, | ||
113 | const gnutls_datum_t * data, | ||
114 | gnutls_x509_crt_fmt_t format) | ||
115 | { | ||
116 | int result = 0, need_free = 0; | ||
117 | gnutls_datum_t _data; | ||
118 | |||
119 | if (crq == NULL) | ||
120 | { | ||
121 | gnutls_assert (); | ||
122 | return GNUTLS_E_INVALID_REQUEST; | ||
123 | } | ||
124 | |||
125 | _data.data = data->data; | ||
126 | _data.size = data->size; | ||
127 | |||
128 | /* If the Certificate is in PEM format then decode it | ||
129 | */ | ||
130 | if (format == GNUTLS_X509_FMT_PEM) | ||
131 | { | ||
132 | opaque *out; | ||
133 | |||
134 | /* Try the first header */ | ||
135 | result = _gnutls_fbase64_decode (PEM_CRQ, data->data, data->size, &out); | ||
136 | |||
137 | if (result <= 0) /* Go for the second header */ | ||
138 | result = | ||
139 | _gnutls_fbase64_decode (PEM_CRQ2, data->data, data->size, &out); | ||
140 | |||
141 | if (result <= 0) | ||
142 | { | ||
143 | if (result == 0) | ||
144 | result = GNUTLS_E_INTERNAL_ERROR; | ||
145 | gnutls_assert (); | ||
146 | return result; | ||
147 | } | ||
148 | |||
149 | _data.data = out; | ||
150 | _data.size = result; | ||
151 | |||
152 | need_free = 1; | ||
153 | } | ||
154 | |||
155 | result = asn1_der_decoding (&crq->crq, _data.data, _data.size, NULL); | ||
156 | if (result != ASN1_SUCCESS) | ||
157 | { | ||
158 | result = _gnutls_asn2err (result); | ||
159 | gnutls_assert (); | ||
160 | goto cleanup; | ||
161 | } | ||
162 | |||
163 | result = 0; | ||
164 | |||
165 | cleanup: | ||
166 | if (need_free) | ||
167 | _gnutls_free_datum (&_data); | ||
168 | return result; | ||
169 | } | ||
170 | |||
171 | |||
172 | |||
173 | /** | ||
174 | * gnutls_x509_crq_get_dn - This function returns the Certificate request subject's distinguished name | ||
175 | * @crq: should contain a gnutls_x509_crq_t structure | ||
176 | * @buf: a pointer to a structure to hold the name (may be null) | ||
177 | * @sizeof_buf: initially holds the size of @buf | ||
178 | * | ||
179 | * This function will copy the name of the Certificate request | ||
180 | * subject in the provided buffer. The name will be in the form | ||
181 | * "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253. The output string | ||
182 | * will be ASCII or UTF-8 encoded, depending on the certificate data. | ||
183 | * | ||
184 | * If @buf is null then only the size will be filled. | ||
185 | * | ||
186 | * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not | ||
187 | * long enough, and in that case the *sizeof_buf will be updated with | ||
188 | * the required size. On success 0 is returned. | ||
189 | * | ||
190 | **/ | ||
191 | int | ||
192 | gnutls_x509_crq_get_dn (gnutls_x509_crq_t crq, char *buf, size_t * sizeof_buf) | ||
193 | { | ||
194 | if (crq == NULL) | ||
195 | { | ||
196 | gnutls_assert (); | ||
197 | return GNUTLS_E_INVALID_REQUEST; | ||
198 | } | ||
199 | |||
200 | return _gnutls_x509_parse_dn (crq->crq, | ||
201 | "certificationRequestInfo.subject.rdnSequence", | ||
202 | buf, sizeof_buf); | ||
203 | } | ||
204 | |||
205 | /** | ||
206 | * gnutls_x509_crq_get_dn_by_oid - This function returns the Certificate request subject's distinguished name | ||
207 | * @crq: should contain a gnutls_x509_crq_t structure | ||
208 | * @oid: holds an Object Identified in null terminated string | ||
209 | * @indx: In case multiple same OIDs exist in the RDN, this specifies | ||
210 | * which to send. Use zero to get the first one. | ||
211 | * @raw_flag: If non zero returns the raw DER data of the DN part. | ||
212 | * @buf: a pointer to a structure to hold the name (may be null) | ||
213 | * @sizeof_buf: initially holds the size of @buf | ||
214 | * | ||
215 | * This function will extract the part of the name of the Certificate | ||
216 | * request subject, specified by the given OID. The output will be | ||
217 | * encoded as described in RFC2253. The output string will be ASCII | ||
218 | * or UTF-8 encoded, depending on the certificate data. | ||
219 | * | ||
220 | * Some helper macros with popular OIDs can be found in gnutls/x509.h | ||
221 | * If raw flag is zero, this function will only return known OIDs as | ||
222 | * text. Other OIDs will be DER encoded, as described in RFC2253 -- | ||
223 | * in hex format with a '\#' prefix. You can check about known OIDs | ||
224 | * using gnutls_x509_dn_oid_known(). | ||
225 | * | ||
226 | * If @buf is null then only the size will be filled. | ||
227 | * | ||
228 | * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not | ||
229 | * long enough, and in that case the *sizeof_buf will be updated with | ||
230 | * the required size. On success 0 is returned. | ||
231 | * | ||
232 | **/ | ||
233 | int | ||
234 | gnutls_x509_crq_get_dn_by_oid (gnutls_x509_crq_t crq, const char *oid, | ||
235 | int indx, unsigned int raw_flag, | ||
236 | void *buf, size_t * sizeof_buf) | ||
237 | { | ||
238 | if (crq == NULL) | ||
239 | { | ||
240 | gnutls_assert (); | ||
241 | return GNUTLS_E_INVALID_REQUEST; | ||
242 | } | ||
243 | |||
244 | return _gnutls_x509_parse_dn_oid (crq->crq, | ||
245 | "certificationRequestInfo.subject.rdnSequence", | ||
246 | oid, indx, raw_flag, buf, sizeof_buf); | ||
247 | } | ||
248 | |||
249 | /** | ||
250 | * gnutls_x509_crq_get_dn_oid - This function returns the Certificate request subject's distinguished name OIDs | ||
251 | * @crq: should contain a gnutls_x509_crq_t structure | ||
252 | * @indx: Specifies which DN OID to send. Use zero to get the first one. | ||
253 | * @oid: a pointer to a structure to hold the name (may be null) | ||
254 | * @sizeof_oid: initially holds the size of @oid | ||
255 | * | ||
256 | * This function will extract the requested OID of the name of the | ||
257 | * Certificate request subject, specified by the given index. | ||
258 | * | ||
259 | * If oid is null then only the size will be filled. | ||
260 | * | ||
261 | * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not | ||
262 | * long enough, and in that case the *sizeof_oid will be updated with | ||
263 | * the required size. On success 0 is returned. | ||
264 | * | ||
265 | **/ | ||
266 | int | ||
267 | gnutls_x509_crq_get_dn_oid (gnutls_x509_crq_t crq, | ||
268 | int indx, void *oid, size_t * sizeof_oid) | ||
269 | { | ||
270 | if (crq == NULL) | ||
271 | { | ||
272 | gnutls_assert (); | ||
273 | return GNUTLS_E_INVALID_REQUEST; | ||
274 | } | ||
275 | |||
276 | return _gnutls_x509_get_dn_oid (crq->crq, | ||
277 | "certificationRequestInfo.subject.rdnSequence", | ||
278 | indx, oid, sizeof_oid); | ||
279 | } | ||
280 | |||
281 | /* Parses an Attribute list in the asn1_struct, and searches for the | ||
282 | * given OID. The index indicates the attribute value to be returned. | ||
283 | * | ||
284 | * If raw==0 only printable data are returned, or GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE. | ||
285 | * | ||
286 | * asn1_attr_name must be a string in the form "certificationRequestInfo.attributes" | ||
287 | * | ||
288 | */ | ||
289 | static int | ||
290 | parse_attribute (ASN1_TYPE asn1_struct, | ||
291 | const char *attr_name, const char *given_oid, int indx, | ||
292 | int raw, char *buf, size_t * sizeof_buf) | ||
293 | { | ||
294 | int k1, result; | ||
295 | char tmpbuffer1[MAX_NAME_SIZE]; | ||
296 | char tmpbuffer3[MAX_NAME_SIZE]; | ||
297 | char value[200]; | ||
298 | char oid[128]; | ||
299 | int len, printable; | ||
300 | |||
301 | if (*sizeof_buf == 0) | ||
302 | { | ||
303 | gnutls_assert (); | ||
304 | return GNUTLS_E_INVALID_REQUEST; | ||
305 | } | ||
306 | |||
307 | buf[0] = 0; | ||
308 | |||
309 | k1 = 0; | ||
310 | do | ||
311 | { | ||
312 | |||
313 | k1++; | ||
314 | /* create a string like "attribute.?1" | ||
315 | */ | ||
316 | if (attr_name[0] != 0) | ||
317 | snprintf (tmpbuffer1, sizeof (tmpbuffer1), "%s.?%u", attr_name, k1); | ||
318 | else | ||
319 | snprintf (tmpbuffer1, sizeof (tmpbuffer1), "?%u", k1); | ||
320 | |||
321 | len = sizeof (value) - 1; | ||
322 | result = asn1_read_value (asn1_struct, tmpbuffer1, value, &len); | ||
323 | |||
324 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
325 | { | ||
326 | gnutls_assert (); | ||
327 | break; | ||
328 | } | ||
329 | |||
330 | if (result != ASN1_VALUE_NOT_FOUND) | ||
331 | { | ||
332 | gnutls_assert (); | ||
333 | result = _gnutls_asn2err (result); | ||
334 | goto cleanup; | ||
335 | } | ||
336 | |||
337 | /* Move to the attibute type and values | ||
338 | */ | ||
339 | /* Read the OID | ||
340 | */ | ||
341 | _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer1); | ||
342 | _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".type"); | ||
343 | |||
344 | len = sizeof (oid) - 1; | ||
345 | result = asn1_read_value (asn1_struct, tmpbuffer3, oid, &len); | ||
346 | |||
347 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
348 | break; | ||
349 | else if (result != ASN1_SUCCESS) | ||
350 | { | ||
351 | gnutls_assert (); | ||
352 | result = _gnutls_asn2err (result); | ||
353 | goto cleanup; | ||
354 | } | ||
355 | |||
356 | if (strcmp (oid, given_oid) == 0) | ||
357 | { /* Found the OID */ | ||
358 | |||
359 | /* Read the Value | ||
360 | */ | ||
361 | snprintf (tmpbuffer3, sizeof (tmpbuffer3), "%s.values.?%u", | ||
362 | tmpbuffer1, indx + 1); | ||
363 | |||
364 | len = sizeof (value) - 1; | ||
365 | result = asn1_read_value (asn1_struct, tmpbuffer3, value, &len); | ||
366 | |||
367 | if (result != ASN1_SUCCESS) | ||
368 | { | ||
369 | gnutls_assert (); | ||
370 | result = _gnutls_asn2err (result); | ||
371 | goto cleanup; | ||
372 | } | ||
373 | |||
374 | if (raw == 0) | ||
375 | { | ||
376 | printable = _gnutls_x509_oid_data_printable (oid); | ||
377 | if (printable == 1) | ||
378 | { | ||
379 | if ((result = | ||
380 | _gnutls_x509_oid_data2string | ||
381 | (oid, value, len, buf, sizeof_buf)) < 0) | ||
382 | { | ||
383 | gnutls_assert (); | ||
384 | goto cleanup; | ||
385 | } | ||
386 | return 0; | ||
387 | } | ||
388 | else | ||
389 | { | ||
390 | gnutls_assert (); | ||
391 | return GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE; | ||
392 | } | ||
393 | } | ||
394 | else | ||
395 | { /* raw!=0 */ | ||
396 | if (*sizeof_buf > (size_t) len && buf != NULL) | ||
397 | { | ||
398 | *sizeof_buf = len; | ||
399 | memcpy (buf, value, len); | ||
400 | |||
401 | return 0; | ||
402 | } | ||
403 | else | ||
404 | { | ||
405 | *sizeof_buf = len; | ||
406 | gnutls_assert (); | ||
407 | return GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
408 | } | ||
409 | } | ||
410 | } | ||
411 | |||
412 | } | ||
413 | while (1); | ||
414 | |||
415 | gnutls_assert (); | ||
416 | |||
417 | result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
418 | |||
419 | cleanup: | ||
420 | return result; | ||
421 | } | ||
422 | |||
423 | /** | ||
424 | * gnutls_x509_crq_get_challenge_password - This function will get the challenge password | ||
425 | * @crq: should contain a gnutls_x509_crq_t structure | ||
426 | * @pass: will hold a null terminated password | ||
427 | * @sizeof_pass: Initially holds the size of @pass. | ||
428 | * | ||
429 | * This function will return the challenge password in the | ||
430 | * request. | ||
431 | * | ||
432 | * Returns 0 on success. | ||
433 | * | ||
434 | **/ | ||
435 | int | ||
436 | gnutls_x509_crq_get_challenge_password (gnutls_x509_crq_t crq, | ||
437 | char *pass, size_t * sizeof_pass) | ||
438 | { | ||
439 | if (crq == NULL) | ||
440 | { | ||
441 | gnutls_assert (); | ||
442 | return GNUTLS_E_INVALID_REQUEST; | ||
443 | } | ||
444 | |||
445 | return parse_attribute (crq->crq, "certificationRequestInfo.attributes", | ||
446 | "1.2.840.113549.1.9.7", 0, 0, pass, sizeof_pass); | ||
447 | } | ||
448 | |||
449 | /** | ||
450 | * gnutls_x509_crq_set_attribute_by_oid - This function will set an attribute in the request | ||
451 | * @crq: should contain a gnutls_x509_crq_t structure | ||
452 | * @oid: holds an Object Identified in null terminated string | ||
453 | * @buf: a pointer to a structure that holds the attribute data | ||
454 | * @sizeof_buf: holds the size of @buf | ||
455 | * | ||
456 | * This function will set the attribute in the certificate request specified | ||
457 | * by the given Object ID. The attribute must be be DER encoded. | ||
458 | * | ||
459 | * Returns 0 on success. | ||
460 | * | ||
461 | **/ | ||
462 | int | ||
463 | gnutls_x509_crq_set_attribute_by_oid (gnutls_x509_crq_t crq, | ||
464 | const char *oid, void *buf, | ||
465 | size_t sizeof_buf) | ||
466 | { | ||
467 | int result; | ||
468 | |||
469 | if (crq == NULL) | ||
470 | { | ||
471 | gnutls_assert (); | ||
472 | return GNUTLS_E_INVALID_REQUEST; | ||
473 | } | ||
474 | |||
475 | /* Add the attribute. | ||
476 | */ | ||
477 | result = | ||
478 | asn1_write_value (crq->crq, "certificationRequestInfo.attributes", | ||
479 | "NEW", 1); | ||
480 | if (result != ASN1_SUCCESS) | ||
481 | { | ||
482 | gnutls_assert (); | ||
483 | return _gnutls_asn2err (result); | ||
484 | } | ||
485 | |||
486 | result = | ||
487 | _gnutls_x509_encode_and_write_attribute (oid, | ||
488 | crq->crq, | ||
489 | "certificationRequestInfo.attributes.?LAST", | ||
490 | buf, sizeof_buf, 1); | ||
491 | |||
492 | if (result < 0) | ||
493 | { | ||
494 | gnutls_assert (); | ||
495 | return result; | ||
496 | } | ||
497 | |||
498 | return 0; | ||
499 | } | ||
500 | |||
501 | /** | ||
502 | * gnutls_x509_crq_get_attribute_by_oid - This function will get an attribute of the request | ||
503 | * @crq: should contain a gnutls_x509_crq_t structure | ||
504 | * @oid: holds an Object Identified in null terminated string | ||
505 | * @indx: In case multiple same OIDs exist in the attribute list, this specifies | ||
506 | * which to send. Use zero to get the first one. | ||
507 | * @buf: a pointer to a structure to hold the attribute data (may be null) | ||
508 | * @sizeof_buf: initially holds the size of @buf | ||
509 | * | ||
510 | * This function will return the attribute in the certificate request specified | ||
511 | * by the given Object ID. The attribute will be DER encoded. | ||
512 | * | ||
513 | * Returns 0 on success. | ||
514 | * | ||
515 | **/ | ||
516 | int | ||
517 | gnutls_x509_crq_get_attribute_by_oid (gnutls_x509_crq_t crq, | ||
518 | const char *oid, int indx, void *buf, | ||
519 | size_t * sizeof_buf) | ||
520 | { | ||
521 | if (crq == NULL) | ||
522 | { | ||
523 | gnutls_assert (); | ||
524 | return GNUTLS_E_INVALID_REQUEST; | ||
525 | } | ||
526 | |||
527 | return parse_attribute (crq->crq, "certificationRequestInfo.attributes", | ||
528 | oid, indx, 1, buf, sizeof_buf); | ||
529 | } | ||
530 | |||
531 | /** | ||
532 | * gnutls_x509_crq_set_dn_by_oid - This function will set the Certificate request subject's distinguished name | ||
533 | * @crq: should contain a gnutls_x509_crq_t structure | ||
534 | * @oid: holds an Object Identifier in a null terminated string | ||
535 | * @raw_flag: must be 0, or 1 if the data are DER encoded | ||
536 | * @data: a pointer to the input data | ||
537 | * @sizeof_data: holds the size of @data | ||
538 | * | ||
539 | * This function will set the part of the name of the Certificate request subject, specified | ||
540 | * by the given OID. The input string should be ASCII or UTF-8 encoded. | ||
541 | * | ||
542 | * Some helper macros with popular OIDs can be found in gnutls/x509.h | ||
543 | * With this function you can only set the known OIDs. You can test | ||
544 | * for known OIDs using gnutls_x509_dn_oid_known(). For OIDs that are | ||
545 | * not known (by gnutls) you should properly DER encode your data, and | ||
546 | * call this function with raw_flag set. | ||
547 | * | ||
548 | * Returns 0 on success. | ||
549 | * | ||
550 | **/ | ||
551 | int | ||
552 | gnutls_x509_crq_set_dn_by_oid (gnutls_x509_crq_t crq, const char *oid, | ||
553 | unsigned int raw_flag, const void *data, | ||
554 | unsigned int sizeof_data) | ||
555 | { | ||
556 | if (sizeof_data == 0 || data == NULL || crq == NULL) | ||
557 | { | ||
558 | return GNUTLS_E_INVALID_REQUEST; | ||
559 | } | ||
560 | |||
561 | return _gnutls_x509_set_dn_oid (crq->crq, | ||
562 | "certificationRequestInfo.subject", oid, | ||
563 | raw_flag, data, sizeof_data); | ||
564 | } | ||
565 | |||
566 | /** | ||
567 | * gnutls_x509_crq_set_version - This function will set the Certificate request version | ||
568 | * @crq: should contain a gnutls_x509_crq_t structure | ||
569 | * @version: holds the version number. For v1 Requests must be 1. | ||
570 | * | ||
571 | * This function will set the version of the certificate request. For | ||
572 | * version 1 requests this must be one. | ||
573 | * | ||
574 | * Returns 0 on success. | ||
575 | * | ||
576 | **/ | ||
577 | int | ||
578 | gnutls_x509_crq_set_version (gnutls_x509_crq_t crq, unsigned int version) | ||
579 | { | ||
580 | int result; | ||
581 | unsigned char null = version; | ||
582 | |||
583 | if (crq == NULL) | ||
584 | { | ||
585 | gnutls_assert (); | ||
586 | return GNUTLS_E_INVALID_REQUEST; | ||
587 | } | ||
588 | |||
589 | if (null > 0) | ||
590 | null--; | ||
591 | |||
592 | result = | ||
593 | asn1_write_value (crq->crq, "certificationRequestInfo.version", &null, 1); | ||
594 | if (result != ASN1_SUCCESS) | ||
595 | { | ||
596 | gnutls_assert (); | ||
597 | return _gnutls_asn2err (result); | ||
598 | } | ||
599 | |||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | /** | ||
604 | * gnutls_x509_crq_get_version - This function returns the Certificate request's version number | ||
605 | * @crq: should contain a gnutls_x509_crq_t structure | ||
606 | * | ||
607 | * This function will return the version of the specified Certificate request. | ||
608 | * | ||
609 | * Returns a negative value on error. | ||
610 | * | ||
611 | **/ | ||
612 | int | ||
613 | gnutls_x509_crq_get_version (gnutls_x509_crq_t crq) | ||
614 | { | ||
615 | opaque version[5]; | ||
616 | int len, result; | ||
617 | |||
618 | if (crq == NULL) | ||
619 | { | ||
620 | gnutls_assert (); | ||
621 | return GNUTLS_E_INVALID_REQUEST; | ||
622 | } | ||
623 | |||
624 | len = sizeof (version); | ||
625 | if ((result = | ||
626 | asn1_read_value (crq->crq, "certificationRequestInfo.version", | ||
627 | version, &len)) != ASN1_SUCCESS) | ||
628 | { | ||
629 | |||
630 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
631 | return 1; /* the DEFAULT version */ | ||
632 | gnutls_assert (); | ||
633 | return _gnutls_asn2err (result); | ||
634 | } | ||
635 | |||
636 | return (int) version[0] + 1; | ||
637 | } | ||
638 | |||
639 | /** | ||
640 | * gnutls_x509_crq_set_key - This function will associate the Certificate request with a key | ||
641 | * @crq: should contain a gnutls_x509_crq_t structure | ||
642 | * @key: holds a private key | ||
643 | * | ||
644 | * This function will set the public parameters from the given private key to the | ||
645 | * request. Only RSA keys are currently supported. | ||
646 | * | ||
647 | * Returns 0 on success. | ||
648 | * | ||
649 | **/ | ||
650 | int | ||
651 | gnutls_x509_crq_set_key (gnutls_x509_crq_t crq, gnutls_x509_privkey_t key) | ||
652 | { | ||
653 | int result; | ||
654 | |||
655 | if (crq == NULL) | ||
656 | { | ||
657 | gnutls_assert (); | ||
658 | return GNUTLS_E_INVALID_REQUEST; | ||
659 | } | ||
660 | |||
661 | result = _gnutls_x509_encode_and_copy_PKI_params (crq->crq, | ||
662 | "certificationRequestInfo.subjectPKInfo", | ||
663 | key->pk_algorithm, | ||
664 | key->params, | ||
665 | key->params_size); | ||
666 | |||
667 | if (result < 0) | ||
668 | { | ||
669 | gnutls_assert (); | ||
670 | return result; | ||
671 | } | ||
672 | |||
673 | return 0; | ||
674 | } | ||
675 | |||
676 | /** | ||
677 | * gnutls_x509_crq_set_challenge_password - This function will set a challenge password | ||
678 | * @crq: should contain a gnutls_x509_crq_t structure | ||
679 | * @pass: holds a null terminated password | ||
680 | * | ||
681 | * This function will set a challenge password to be used when revoking the request. | ||
682 | * | ||
683 | * Returns 0 on success. | ||
684 | * | ||
685 | **/ | ||
686 | int | ||
687 | gnutls_x509_crq_set_challenge_password (gnutls_x509_crq_t crq, | ||
688 | const char *pass) | ||
689 | { | ||
690 | int result; | ||
691 | |||
692 | if (crq == NULL) | ||
693 | { | ||
694 | gnutls_assert (); | ||
695 | return GNUTLS_E_INVALID_REQUEST; | ||
696 | } | ||
697 | |||
698 | /* Add the attribute. | ||
699 | */ | ||
700 | result = | ||
701 | asn1_write_value (crq->crq, "certificationRequestInfo.attributes", | ||
702 | "NEW", 1); | ||
703 | if (result != ASN1_SUCCESS) | ||
704 | { | ||
705 | gnutls_assert (); | ||
706 | return _gnutls_asn2err (result); | ||
707 | } | ||
708 | |||
709 | result = | ||
710 | _gnutls_x509_encode_and_write_attribute ("1.2.840.113549.1.9.7", | ||
711 | crq->crq, | ||
712 | "certificationRequestInfo.attributes.?LAST", | ||
713 | pass, strlen (pass), 1); | ||
714 | |||
715 | if (result < 0) | ||
716 | { | ||
717 | gnutls_assert (); | ||
718 | return result; | ||
719 | } | ||
720 | |||
721 | return 0; | ||
722 | } | ||
723 | |||
724 | /** | ||
725 | * gnutls_x509_crq_sign2 - This function will sign a Certificate request with a key | ||
726 | * @crq: should contain a gnutls_x509_crq_t structure | ||
727 | * @key: holds a private key | ||
728 | * @dig: The message digest to use. GNUTLS_DIG_SHA1 is the safe choice unless you know what you're doing. | ||
729 | * @flags: must be 0 | ||
730 | * | ||
731 | * This function will sign the certificate request with a private key. | ||
732 | * This must be the same key as the one used in gnutls_x509_crt_set_key() since a | ||
733 | * certificate request is self signed. | ||
734 | * | ||
735 | * This must be the last step in a certificate request generation since all | ||
736 | * the previously set parameters are now signed. | ||
737 | * | ||
738 | * Returns 0 on success. | ||
739 | * | ||
740 | **/ | ||
741 | int | ||
742 | gnutls_x509_crq_sign2 (gnutls_x509_crq_t crq, gnutls_x509_privkey_t key, | ||
743 | gnutls_digest_algorithm_t dig, unsigned int flags) | ||
744 | { | ||
745 | int result; | ||
746 | gnutls_datum_t signature; | ||
747 | |||
748 | if (crq == NULL) | ||
749 | { | ||
750 | gnutls_assert (); | ||
751 | return GNUTLS_E_INVALID_REQUEST; | ||
752 | } | ||
753 | |||
754 | /* Step 1. Self sign the request. | ||
755 | */ | ||
756 | result = | ||
757 | _gnutls_x509_sign_tbs (crq->crq, "certificationRequestInfo", | ||
758 | dig, key, &signature); | ||
759 | |||
760 | if (result < 0) | ||
761 | { | ||
762 | gnutls_assert (); | ||
763 | return result; | ||
764 | } | ||
765 | |||
766 | /* Step 2. write the signature (bits) | ||
767 | */ | ||
768 | result = | ||
769 | asn1_write_value (crq->crq, "signature", signature.data, | ||
770 | signature.size * 8); | ||
771 | |||
772 | _gnutls_free_datum (&signature); | ||
773 | |||
774 | if (result != ASN1_SUCCESS) | ||
775 | { | ||
776 | gnutls_assert (); | ||
777 | return _gnutls_asn2err (result); | ||
778 | } | ||
779 | |||
780 | /* Step 3. Write the signatureAlgorithm field. | ||
781 | */ | ||
782 | result = _gnutls_x509_write_sig_params (crq->crq, "signatureAlgorithm", | ||
783 | key->pk_algorithm, dig, key->params, | ||
784 | key->params_size); | ||
785 | if (result < 0) | ||
786 | { | ||
787 | gnutls_assert (); | ||
788 | return result; | ||
789 | } | ||
790 | |||
791 | return 0; | ||
792 | } | ||
793 | |||
794 | /** | ||
795 | * gnutls_x509_crq_sign - This function will sign a Certificate request with a key | ||
796 | * @crq: should contain a gnutls_x509_crq_t structure | ||
797 | * @key: holds a private key | ||
798 | * | ||
799 | * This function is the same a gnutls_x509_crq_sign2() with no flags, and | ||
800 | * SHA1 as the hash algorithm. | ||
801 | * | ||
802 | * Returns 0 on success. | ||
803 | * | ||
804 | **/ | ||
805 | int | ||
806 | gnutls_x509_crq_sign (gnutls_x509_crq_t crq, gnutls_x509_privkey_t key) | ||
807 | { | ||
808 | return gnutls_x509_crq_sign2 (crq, key, GNUTLS_DIG_SHA1, 0); | ||
809 | } | ||
810 | |||
811 | /** | ||
812 | * gnutls_x509_crq_export - Export the generated certificate request | ||
813 | * @crq: Holds the request | ||
814 | * @format: the format of output params. One of PEM or DER. | ||
815 | * @output_data: will contain a certificate request PEM or DER encoded | ||
816 | * @output_data_size: holds the size of output_data (and will be | ||
817 | * replaced by the actual size of parameters) | ||
818 | * | ||
819 | * This function will export the certificate request to a PKCS10 | ||
820 | * | ||
821 | * If the buffer provided is not long enough to hold the output, then | ||
822 | * GNUTLS_E_SHORT_MEMORY_BUFFER will be returned and | ||
823 | * *output_data_size will be updated. | ||
824 | * | ||
825 | * If the structure is PEM encoded, it will have a header of "BEGIN | ||
826 | * NEW CERTIFICATE REQUEST". | ||
827 | * | ||
828 | * Return value: In case of failure a negative value will be | ||
829 | * returned, and 0 on success. | ||
830 | * | ||
831 | **/ | ||
832 | int | ||
833 | gnutls_x509_crq_export (gnutls_x509_crq_t crq, | ||
834 | gnutls_x509_crt_fmt_t format, void *output_data, | ||
835 | size_t * output_data_size) | ||
836 | { | ||
837 | if (crq == NULL) | ||
838 | { | ||
839 | gnutls_assert (); | ||
840 | return GNUTLS_E_INVALID_REQUEST; | ||
841 | } | ||
842 | |||
843 | return _gnutls_x509_export_int (crq->crq, format, PEM_CRQ, | ||
844 | output_data, output_data_size); | ||
845 | } | ||
846 | |||
847 | /** | ||
848 | * gnutls_x509_crq_get_pk_algorithm - This function returns the certificate request's PublicKey algorithm | ||
849 | * @crq: should contain a gnutls_x509_crq_t structure | ||
850 | * @bits: if bits is non null it will hold the size of the parameters' in bits | ||
851 | * | ||
852 | * This function will return the public key algorithm of a PKCS \#10 | ||
853 | * certificate request. | ||
854 | * | ||
855 | * If bits is non null, it should have enough size to hold the parameters | ||
856 | * size in bits. For RSA the bits returned is the modulus. | ||
857 | * For DSA the bits returned are of the public | ||
858 | * exponent. | ||
859 | * | ||
860 | * Returns a member of the gnutls_pk_algorithm_t enumeration on success, | ||
861 | * or a negative value on error. | ||
862 | * | ||
863 | **/ | ||
864 | int | ||
865 | gnutls_x509_crq_get_pk_algorithm (gnutls_x509_crq_t crq, unsigned int *bits) | ||
866 | { | ||
867 | int result; | ||
868 | |||
869 | if (crq == NULL) | ||
870 | { | ||
871 | gnutls_assert (); | ||
872 | return GNUTLS_E_INVALID_REQUEST; | ||
873 | } | ||
874 | |||
875 | result = | ||
876 | _gnutls_x509_get_pk_algorithm (crq->crq, | ||
877 | "certificationRequestInfo.subjectPKInfo", | ||
878 | bits); | ||
879 | if (result < 0) | ||
880 | { | ||
881 | gnutls_assert (); | ||
882 | } | ||
883 | |||
884 | return result; | ||
885 | } | ||
886 | |||
887 | #endif /* ENABLE_PKI */ | ||
diff --git a/src/daemon/https/x509/crq.h b/src/daemon/https/x509/crq.h new file mode 100644 index 00000000..80e600b5 --- /dev/null +++ b/src/daemon/https/x509/crq.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <x509.h> | ||
26 | |||
27 | typedef struct gnutls_x509_crq_int | ||
28 | { | ||
29 | ASN1_TYPE crq; | ||
30 | } gnutls_x509_crq_int; | ||
diff --git a/src/daemon/https/x509/dn.c b/src/daemon/https/x509/dn.c new file mode 100644 index 00000000..c356aac1 --- /dev/null +++ b/src/daemon/https/x509/dn.c | |||
@@ -0,0 +1,1140 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <gnutls_int.h> | ||
26 | #include <libtasn1.h> | ||
27 | #include <gnutls_datum.h> | ||
28 | #include <gnutls_global.h> | ||
29 | #include <gnutls_errors.h> | ||
30 | #include <gnutls_str.h> | ||
31 | #include <common.h> | ||
32 | #include <gnutls_num.h> | ||
33 | #include <dn.h> | ||
34 | |||
35 | /* This file includes all the required to parse an X.509 Distriguished | ||
36 | * Name (you need a parser just to read a name in the X.509 protoocols!!!) | ||
37 | */ | ||
38 | |||
39 | /* Converts the given OID to an ldap acceptable string or | ||
40 | * a dotted OID. | ||
41 | */ | ||
42 | static const char * | ||
43 | oid2ldap_string (const char *oid) | ||
44 | { | ||
45 | const char *ret; | ||
46 | |||
47 | ret = _gnutls_x509_oid2ldap_string (oid); | ||
48 | if (ret) | ||
49 | return ret; | ||
50 | |||
51 | /* else return the OID in dotted format */ | ||
52 | return oid; | ||
53 | } | ||
54 | |||
55 | /* Escapes a string following the rules from RFC2253. | ||
56 | */ | ||
57 | static char * | ||
58 | str_escape (char *str, char *buffer, unsigned int buffer_size) | ||
59 | { | ||
60 | int str_length, j, i; | ||
61 | |||
62 | if (str == NULL || buffer == NULL) | ||
63 | return NULL; | ||
64 | |||
65 | str_length = MIN (strlen (str), buffer_size - 1); | ||
66 | |||
67 | for (i = j = 0; i < str_length; i++) | ||
68 | { | ||
69 | if (str[i] == ',' || str[i] == '+' || str[i] == '"' | ||
70 | || str[i] == '\\' || str[i] == '<' || str[i] == '>' | ||
71 | || str[i] == ';') | ||
72 | buffer[j++] = '\\'; | ||
73 | |||
74 | buffer[j++] = str[i]; | ||
75 | } | ||
76 | |||
77 | /* null terminate the string */ | ||
78 | buffer[j] = 0; | ||
79 | |||
80 | return buffer; | ||
81 | } | ||
82 | |||
83 | /* Parses an X509 DN in the asn1_struct, and puts the output into | ||
84 | * the string buf. The output is an LDAP encoded DN. | ||
85 | * | ||
86 | * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence". | ||
87 | * That is to point in the rndSequence. | ||
88 | */ | ||
89 | int | ||
90 | _gnutls_x509_parse_dn (ASN1_TYPE asn1_struct, | ||
91 | const char *asn1_rdn_name, char *buf, | ||
92 | size_t * sizeof_buf) | ||
93 | { | ||
94 | gnutls_string out_str; | ||
95 | int k2, k1, result; | ||
96 | char tmpbuffer1[MAX_NAME_SIZE]; | ||
97 | char tmpbuffer2[MAX_NAME_SIZE]; | ||
98 | char tmpbuffer3[MAX_NAME_SIZE]; | ||
99 | opaque value[MAX_STRING_LEN], *value2 = NULL; | ||
100 | char *escaped = NULL; | ||
101 | const char *ldap_desc; | ||
102 | char oid[128]; | ||
103 | int len, printable; | ||
104 | char *string = NULL; | ||
105 | size_t sizeof_string, sizeof_escaped; | ||
106 | |||
107 | if (sizeof_buf == NULL) | ||
108 | { | ||
109 | gnutls_assert (); | ||
110 | return GNUTLS_E_INVALID_REQUEST; | ||
111 | } | ||
112 | |||
113 | if (*sizeof_buf > 0 && buf) | ||
114 | buf[0] = 0; | ||
115 | else | ||
116 | *sizeof_buf = 0; | ||
117 | |||
118 | _gnutls_string_init (&out_str, gnutls_malloc, gnutls_realloc, gnutls_free); | ||
119 | |||
120 | k1 = 0; | ||
121 | do | ||
122 | { | ||
123 | |||
124 | k1++; | ||
125 | /* create a string like "tbsCertList.issuer.rdnSequence.?1" | ||
126 | */ | ||
127 | if (asn1_rdn_name[0] != 0) | ||
128 | snprintf (tmpbuffer1, sizeof (tmpbuffer1), "%s.?%u", asn1_rdn_name, | ||
129 | k1); | ||
130 | else | ||
131 | snprintf (tmpbuffer1, sizeof (tmpbuffer1), "?%u", k1); | ||
132 | |||
133 | len = sizeof (value) - 1; | ||
134 | result = asn1_read_value (asn1_struct, tmpbuffer1, value, &len); | ||
135 | |||
136 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
137 | { | ||
138 | break; | ||
139 | } | ||
140 | |||
141 | if (result != ASN1_VALUE_NOT_FOUND) | ||
142 | { | ||
143 | gnutls_assert (); | ||
144 | result = _gnutls_asn2err (result); | ||
145 | goto cleanup; | ||
146 | } | ||
147 | |||
148 | k2 = 0; | ||
149 | |||
150 | do | ||
151 | { /* Move to the attibute type and values | ||
152 | */ | ||
153 | k2++; | ||
154 | |||
155 | if (tmpbuffer1[0] != 0) | ||
156 | snprintf (tmpbuffer2, sizeof (tmpbuffer2), "%s.?%u", tmpbuffer1, | ||
157 | k2); | ||
158 | else | ||
159 | snprintf (tmpbuffer2, sizeof (tmpbuffer2), "?%u", k2); | ||
160 | |||
161 | /* Try to read the RelativeDistinguishedName attributes. | ||
162 | */ | ||
163 | |||
164 | len = sizeof (value) - 1; | ||
165 | result = asn1_read_value (asn1_struct, tmpbuffer2, value, &len); | ||
166 | |||
167 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
168 | break; | ||
169 | if (result != ASN1_VALUE_NOT_FOUND) | ||
170 | { | ||
171 | gnutls_assert (); | ||
172 | result = _gnutls_asn2err (result); | ||
173 | goto cleanup; | ||
174 | } | ||
175 | |||
176 | /* Read the OID | ||
177 | */ | ||
178 | _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2); | ||
179 | _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".type"); | ||
180 | |||
181 | len = sizeof (oid) - 1; | ||
182 | result = asn1_read_value (asn1_struct, tmpbuffer3, oid, &len); | ||
183 | |||
184 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
185 | break; | ||
186 | else if (result != ASN1_SUCCESS) | ||
187 | { | ||
188 | gnutls_assert (); | ||
189 | result = _gnutls_asn2err (result); | ||
190 | goto cleanup; | ||
191 | } | ||
192 | |||
193 | /* Read the Value | ||
194 | */ | ||
195 | _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2); | ||
196 | _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".value"); | ||
197 | |||
198 | len = 0; | ||
199 | result = asn1_read_value (asn1_struct, tmpbuffer3, NULL, &len); | ||
200 | |||
201 | value2 = gnutls_malloc (len); | ||
202 | if (value2 == NULL) | ||
203 | { | ||
204 | gnutls_assert (); | ||
205 | result = GNUTLS_E_MEMORY_ERROR; | ||
206 | goto cleanup; | ||
207 | } | ||
208 | |||
209 | result = asn1_read_value (asn1_struct, tmpbuffer3, value2, &len); | ||
210 | |||
211 | if (result != ASN1_SUCCESS) | ||
212 | { | ||
213 | gnutls_assert (); | ||
214 | result = _gnutls_asn2err (result); | ||
215 | goto cleanup; | ||
216 | } | ||
217 | #define STR_APPEND(y) if ((result=_gnutls_string_append_str( &out_str, y)) < 0) { \ | ||
218 | gnutls_assert(); \ | ||
219 | goto cleanup; \ | ||
220 | } | ||
221 | /* The encodings of adjoining RelativeDistinguishedNames are separated | ||
222 | * by a comma character (',' ASCII 44). | ||
223 | */ | ||
224 | |||
225 | /* Where there is a multi-valued RDN, the outputs from adjoining | ||
226 | * AttributeTypeAndValues are separated by a plus ('+' ASCII 43) | ||
227 | * character. | ||
228 | */ | ||
229 | if (k1 != 1) | ||
230 | { /* the first time do not append a comma */ | ||
231 | if (k2 != 1) | ||
232 | { /* adjoining multi-value RDN */ | ||
233 | STR_APPEND ("+"); | ||
234 | } | ||
235 | else | ||
236 | { | ||
237 | STR_APPEND (","); | ||
238 | } | ||
239 | } | ||
240 | |||
241 | ldap_desc = oid2ldap_string (oid); | ||
242 | printable = _gnutls_x509_oid_data_printable (oid); | ||
243 | |||
244 | sizeof_escaped = 2 * len + 1; | ||
245 | |||
246 | escaped = gnutls_malloc (sizeof_escaped); | ||
247 | if (escaped == NULL) | ||
248 | { | ||
249 | gnutls_assert (); | ||
250 | result = GNUTLS_E_MEMORY_ERROR; | ||
251 | goto cleanup; | ||
252 | } | ||
253 | |||
254 | sizeof_string = 2 * len + 2; /* in case it is not printable */ | ||
255 | |||
256 | string = gnutls_malloc (sizeof_string); | ||
257 | if (string == NULL) | ||
258 | { | ||
259 | gnutls_assert (); | ||
260 | result = GNUTLS_E_MEMORY_ERROR; | ||
261 | goto cleanup; | ||
262 | } | ||
263 | |||
264 | STR_APPEND (ldap_desc); | ||
265 | STR_APPEND ("="); | ||
266 | result = 0; | ||
267 | |||
268 | if (printable) | ||
269 | result = | ||
270 | _gnutls_x509_oid_data2string (oid, | ||
271 | value2, len, | ||
272 | string, &sizeof_string); | ||
273 | |||
274 | if (!printable || result < 0) | ||
275 | result = | ||
276 | _gnutls_x509_data2hex (value2, len, string, &sizeof_string); | ||
277 | |||
278 | if (result < 0) | ||
279 | { | ||
280 | gnutls_assert (); | ||
281 | _gnutls_x509_log | ||
282 | ("Found OID: '%s' with value '%s'\n", | ||
283 | oid, _gnutls_bin2hex (value2, len, escaped, sizeof_escaped)); | ||
284 | goto cleanup; | ||
285 | } | ||
286 | STR_APPEND (str_escape (string, escaped, sizeof_escaped)); | ||
287 | gnutls_free (string); | ||
288 | string = NULL; | ||
289 | |||
290 | gnutls_free (escaped); | ||
291 | escaped = NULL; | ||
292 | gnutls_free (value2); | ||
293 | value2 = NULL; | ||
294 | |||
295 | } | ||
296 | while (1); | ||
297 | |||
298 | } | ||
299 | while (1); | ||
300 | |||
301 | if (out_str.length >= (unsigned int) *sizeof_buf) | ||
302 | { | ||
303 | gnutls_assert (); | ||
304 | *sizeof_buf = out_str.length + 1; | ||
305 | result = GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
306 | goto cleanup; | ||
307 | } | ||
308 | |||
309 | if (buf) | ||
310 | { | ||
311 | memcpy (buf, out_str.data, out_str.length); | ||
312 | buf[out_str.length] = 0; | ||
313 | } | ||
314 | *sizeof_buf = out_str.length; | ||
315 | |||
316 | result = 0; | ||
317 | |||
318 | cleanup: | ||
319 | gnutls_free (value2); | ||
320 | gnutls_free (string); | ||
321 | gnutls_free (escaped); | ||
322 | _gnutls_string_clear (&out_str); | ||
323 | return result; | ||
324 | } | ||
325 | |||
326 | /* Parses an X509 DN in the asn1_struct, and searches for the | ||
327 | * given OID in the DN. | ||
328 | * | ||
329 | * If raw_flag == 0, the output will be encoded in the LDAP way. (#hex for non printable) | ||
330 | * Otherwise the raw DER data are returned. | ||
331 | * | ||
332 | * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence". | ||
333 | * That is to point in the rndSequence. | ||
334 | * | ||
335 | * indx specifies which OID to return. Ie 0 means return the first specified | ||
336 | * OID found, 1 the second etc. | ||
337 | */ | ||
338 | int | ||
339 | _gnutls_x509_parse_dn_oid (ASN1_TYPE asn1_struct, | ||
340 | const char *asn1_rdn_name, | ||
341 | const char *given_oid, int indx, | ||
342 | unsigned int raw_flag, | ||
343 | void *buf, size_t * sizeof_buf) | ||
344 | { | ||
345 | int k2, k1, result; | ||
346 | char tmpbuffer1[MAX_NAME_SIZE]; | ||
347 | char tmpbuffer2[MAX_NAME_SIZE]; | ||
348 | char tmpbuffer3[MAX_NAME_SIZE]; | ||
349 | opaque value[256]; | ||
350 | char oid[128]; | ||
351 | int len, printable; | ||
352 | int i = 0; | ||
353 | char *cbuf = buf; | ||
354 | |||
355 | if (cbuf == NULL) | ||
356 | *sizeof_buf = 0; | ||
357 | else | ||
358 | cbuf[0] = 0; | ||
359 | |||
360 | k1 = 0; | ||
361 | do | ||
362 | { | ||
363 | |||
364 | k1++; | ||
365 | /* create a string like "tbsCertList.issuer.rdnSequence.?1" | ||
366 | */ | ||
367 | if (asn1_rdn_name[0] != 0) | ||
368 | snprintf (tmpbuffer1, sizeof (tmpbuffer1), "%s.?%u", asn1_rdn_name, | ||
369 | k1); | ||
370 | else | ||
371 | snprintf (tmpbuffer1, sizeof (tmpbuffer1), "?%u", k1); | ||
372 | |||
373 | len = sizeof (value) - 1; | ||
374 | result = asn1_read_value (asn1_struct, tmpbuffer1, value, &len); | ||
375 | |||
376 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
377 | { | ||
378 | gnutls_assert (); | ||
379 | break; | ||
380 | } | ||
381 | |||
382 | if (result != ASN1_VALUE_NOT_FOUND) | ||
383 | { | ||
384 | gnutls_assert (); | ||
385 | result = _gnutls_asn2err (result); | ||
386 | goto cleanup; | ||
387 | } | ||
388 | |||
389 | k2 = 0; | ||
390 | |||
391 | do | ||
392 | { /* Move to the attibute type and values | ||
393 | */ | ||
394 | k2++; | ||
395 | |||
396 | if (tmpbuffer1[0] != 0) | ||
397 | snprintf (tmpbuffer2, sizeof (tmpbuffer2), "%s.?%u", tmpbuffer1, | ||
398 | k2); | ||
399 | else | ||
400 | snprintf (tmpbuffer2, sizeof (tmpbuffer2), "?%u", k2); | ||
401 | |||
402 | /* Try to read the RelativeDistinguishedName attributes. | ||
403 | */ | ||
404 | |||
405 | len = sizeof (value) - 1; | ||
406 | result = asn1_read_value (asn1_struct, tmpbuffer2, value, &len); | ||
407 | |||
408 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
409 | { | ||
410 | break; | ||
411 | } | ||
412 | if (result != ASN1_VALUE_NOT_FOUND) | ||
413 | { | ||
414 | gnutls_assert (); | ||
415 | result = _gnutls_asn2err (result); | ||
416 | goto cleanup; | ||
417 | } | ||
418 | |||
419 | /* Read the OID | ||
420 | */ | ||
421 | _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2); | ||
422 | _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".type"); | ||
423 | |||
424 | len = sizeof (oid) - 1; | ||
425 | result = asn1_read_value (asn1_struct, tmpbuffer3, oid, &len); | ||
426 | |||
427 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
428 | break; | ||
429 | else if (result != ASN1_SUCCESS) | ||
430 | { | ||
431 | gnutls_assert (); | ||
432 | result = _gnutls_asn2err (result); | ||
433 | goto cleanup; | ||
434 | } | ||
435 | |||
436 | if (strcmp (oid, given_oid) == 0 && indx == i++) | ||
437 | { /* Found the OID */ | ||
438 | |||
439 | /* Read the Value | ||
440 | */ | ||
441 | _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2); | ||
442 | _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".value"); | ||
443 | |||
444 | len = *sizeof_buf; | ||
445 | result = asn1_read_value (asn1_struct, tmpbuffer3, buf, &len); | ||
446 | |||
447 | if (result != ASN1_SUCCESS) | ||
448 | { | ||
449 | gnutls_assert (); | ||
450 | if (result == ASN1_MEM_ERROR) | ||
451 | *sizeof_buf = len; | ||
452 | result = _gnutls_asn2err (result); | ||
453 | goto cleanup; | ||
454 | } | ||
455 | |||
456 | if (raw_flag != 0) | ||
457 | { | ||
458 | if ((unsigned) len > *sizeof_buf) | ||
459 | { | ||
460 | *sizeof_buf = len; | ||
461 | result = GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
462 | goto cleanup; | ||
463 | } | ||
464 | *sizeof_buf = len; | ||
465 | |||
466 | return 0; | ||
467 | |||
468 | } | ||
469 | else | ||
470 | { /* parse data. raw_flag == 0 */ | ||
471 | printable = _gnutls_x509_oid_data_printable (oid); | ||
472 | |||
473 | if (printable == 1) | ||
474 | result = | ||
475 | _gnutls_x509_oid_data2string (oid, buf, len, | ||
476 | cbuf, sizeof_buf); | ||
477 | else | ||
478 | result = | ||
479 | _gnutls_x509_data2hex (buf, len, cbuf, sizeof_buf); | ||
480 | |||
481 | if (result < 0) | ||
482 | { | ||
483 | gnutls_assert (); | ||
484 | goto cleanup; | ||
485 | } | ||
486 | |||
487 | return 0; | ||
488 | |||
489 | } /* raw_flag == 0 */ | ||
490 | } | ||
491 | } | ||
492 | while (1); | ||
493 | |||
494 | } | ||
495 | while (1); | ||
496 | |||
497 | gnutls_assert (); | ||
498 | |||
499 | result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
500 | |||
501 | cleanup: | ||
502 | return result; | ||
503 | } | ||
504 | |||
505 | |||
506 | /* Parses an X509 DN in the asn1_struct, and returns the requested | ||
507 | * DN OID. | ||
508 | * | ||
509 | * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence". | ||
510 | * That is to point in the rndSequence. | ||
511 | * | ||
512 | * indx specifies which OID to return. Ie 0 means return the first specified | ||
513 | * OID found, 1 the second etc. | ||
514 | */ | ||
515 | int | ||
516 | _gnutls_x509_get_dn_oid (ASN1_TYPE asn1_struct, | ||
517 | const char *asn1_rdn_name, | ||
518 | int indx, void *_oid, size_t * sizeof_oid) | ||
519 | { | ||
520 | int k2, k1, result; | ||
521 | char tmpbuffer1[MAX_NAME_SIZE]; | ||
522 | char tmpbuffer2[MAX_NAME_SIZE]; | ||
523 | char tmpbuffer3[MAX_NAME_SIZE]; | ||
524 | char value[256]; | ||
525 | char oid[128]; | ||
526 | int len; | ||
527 | int i = 0; | ||
528 | |||
529 | k1 = 0; | ||
530 | do | ||
531 | { | ||
532 | |||
533 | k1++; | ||
534 | /* create a string like "tbsCertList.issuer.rdnSequence.?1" | ||
535 | */ | ||
536 | if (asn1_rdn_name[0] != 0) | ||
537 | snprintf (tmpbuffer1, sizeof (tmpbuffer1), "%s.?%u", asn1_rdn_name, | ||
538 | k1); | ||
539 | else | ||
540 | snprintf (tmpbuffer1, sizeof (tmpbuffer1), "?%u", k1); | ||
541 | |||
542 | len = sizeof (value) - 1; | ||
543 | result = asn1_read_value (asn1_struct, tmpbuffer1, value, &len); | ||
544 | |||
545 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
546 | { | ||
547 | gnutls_assert (); | ||
548 | break; | ||
549 | } | ||
550 | |||
551 | if (result != ASN1_VALUE_NOT_FOUND) | ||
552 | { | ||
553 | gnutls_assert (); | ||
554 | result = _gnutls_asn2err (result); | ||
555 | goto cleanup; | ||
556 | } | ||
557 | |||
558 | k2 = 0; | ||
559 | |||
560 | do | ||
561 | { /* Move to the attibute type and values | ||
562 | */ | ||
563 | k2++; | ||
564 | |||
565 | if (tmpbuffer1[0] != 0) | ||
566 | snprintf (tmpbuffer2, sizeof (tmpbuffer2), "%s.?%u", tmpbuffer1, | ||
567 | k2); | ||
568 | else | ||
569 | snprintf (tmpbuffer2, sizeof (tmpbuffer2), "?%u", k2); | ||
570 | |||
571 | /* Try to read the RelativeDistinguishedName attributes. | ||
572 | */ | ||
573 | |||
574 | len = sizeof (value) - 1; | ||
575 | result = asn1_read_value (asn1_struct, tmpbuffer2, value, &len); | ||
576 | |||
577 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
578 | { | ||
579 | break; | ||
580 | } | ||
581 | if (result != ASN1_VALUE_NOT_FOUND) | ||
582 | { | ||
583 | gnutls_assert (); | ||
584 | result = _gnutls_asn2err (result); | ||
585 | goto cleanup; | ||
586 | } | ||
587 | |||
588 | /* Read the OID | ||
589 | */ | ||
590 | _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2); | ||
591 | _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".type"); | ||
592 | |||
593 | len = sizeof (oid) - 1; | ||
594 | result = asn1_read_value (asn1_struct, tmpbuffer3, oid, &len); | ||
595 | |||
596 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
597 | break; | ||
598 | else if (result != ASN1_SUCCESS) | ||
599 | { | ||
600 | gnutls_assert (); | ||
601 | result = _gnutls_asn2err (result); | ||
602 | goto cleanup; | ||
603 | } | ||
604 | |||
605 | if (indx == i++) | ||
606 | { /* Found the OID */ | ||
607 | |||
608 | len = strlen (oid) + 1; | ||
609 | |||
610 | if (*sizeof_oid < (unsigned) len) | ||
611 | { | ||
612 | *sizeof_oid = len; | ||
613 | gnutls_assert (); | ||
614 | return GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
615 | } | ||
616 | |||
617 | memcpy (_oid, oid, len); | ||
618 | *sizeof_oid = len - 1; | ||
619 | |||
620 | return 0; | ||
621 | } | ||
622 | } | ||
623 | while (1); | ||
624 | |||
625 | } | ||
626 | while (1); | ||
627 | |||
628 | gnutls_assert (); | ||
629 | |||
630 | result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
631 | |||
632 | cleanup: | ||
633 | return result; | ||
634 | } | ||
635 | |||
636 | /* This will encode and write the AttributeTypeAndValue field. | ||
637 | * 'multi' must be zero if writing an AttributeTypeAndValue, and 1 if Attribute. | ||
638 | * In all cases only one value is written. | ||
639 | */ | ||
640 | int | ||
641 | _gnutls_x509_encode_and_write_attribute (const char *given_oid, | ||
642 | ASN1_TYPE asn1_struct, | ||
643 | const char *where, | ||
644 | const void *_data, | ||
645 | int sizeof_data, int multi) | ||
646 | { | ||
647 | const char *val_name; | ||
648 | const opaque *data = _data; | ||
649 | char tmp[128]; | ||
650 | ASN1_TYPE c2; | ||
651 | int result; | ||
652 | |||
653 | |||
654 | /* Find how to encode the data. | ||
655 | */ | ||
656 | val_name = asn1_find_structure_from_oid (_gnutls_get_pkix (), given_oid); | ||
657 | if (val_name == NULL) | ||
658 | { | ||
659 | gnutls_assert (); | ||
660 | return GNUTLS_E_X509_UNSUPPORTED_OID; | ||
661 | } | ||
662 | |||
663 | _gnutls_str_cpy (tmp, sizeof (tmp), "PKIX1."); | ||
664 | _gnutls_str_cat (tmp, sizeof (tmp), val_name); | ||
665 | |||
666 | result = asn1_create_element (_gnutls_get_pkix (), tmp, &c2); | ||
667 | if (result != ASN1_SUCCESS) | ||
668 | { | ||
669 | gnutls_assert (); | ||
670 | return _gnutls_asn2err (result); | ||
671 | } | ||
672 | |||
673 | tmp[0] = 0; | ||
674 | |||
675 | if ((result = _gnutls_x509_oid_data_choice (given_oid)) > 0) | ||
676 | { | ||
677 | char *string_type; | ||
678 | int i; | ||
679 | |||
680 | string_type = "printableString"; | ||
681 | |||
682 | /* Check if the data is plain ascii, and use | ||
683 | * the UTF8 string type if not. | ||
684 | */ | ||
685 | for (i = 0; i < sizeof_data; i++) | ||
686 | { | ||
687 | if (!isascii (data[i])) | ||
688 | { | ||
689 | string_type = "utf8String"; | ||
690 | break; | ||
691 | } | ||
692 | } | ||
693 | |||
694 | /* if the type is a CHOICE then write the | ||
695 | * type we'll use. | ||
696 | */ | ||
697 | result = asn1_write_value (c2, "", string_type, 1); | ||
698 | if (result != ASN1_SUCCESS) | ||
699 | { | ||
700 | gnutls_assert (); | ||
701 | asn1_delete_structure (&c2); | ||
702 | return _gnutls_asn2err (result); | ||
703 | } | ||
704 | |||
705 | _gnutls_str_cpy (tmp, sizeof (tmp), string_type); | ||
706 | } | ||
707 | |||
708 | result = asn1_write_value (c2, tmp, data, sizeof_data); | ||
709 | if (result != ASN1_SUCCESS) | ||
710 | { | ||
711 | gnutls_assert (); | ||
712 | asn1_delete_structure (&c2); | ||
713 | return _gnutls_asn2err (result); | ||
714 | } | ||
715 | |||
716 | |||
717 | /* write the data (value) | ||
718 | */ | ||
719 | |||
720 | _gnutls_str_cpy (tmp, sizeof (tmp), where); | ||
721 | _gnutls_str_cat (tmp, sizeof (tmp), ".value"); | ||
722 | |||
723 | if (multi != 0) | ||
724 | { /* if not writing an AttributeTypeAndValue, but an Attribute */ | ||
725 | _gnutls_str_cat (tmp, sizeof (tmp), "s"); /* values */ | ||
726 | |||
727 | result = asn1_write_value (asn1_struct, tmp, "NEW", 1); | ||
728 | if (result != ASN1_SUCCESS) | ||
729 | { | ||
730 | gnutls_assert (); | ||
731 | return _gnutls_asn2err (result); | ||
732 | } | ||
733 | |||
734 | _gnutls_str_cat (tmp, sizeof (tmp), ".?LAST"); | ||
735 | |||
736 | } | ||
737 | |||
738 | result = _gnutls_x509_der_encode_and_copy (c2, "", asn1_struct, tmp, 0); | ||
739 | if (result < 0) | ||
740 | { | ||
741 | gnutls_assert (); | ||
742 | return result; | ||
743 | } | ||
744 | |||
745 | /* write the type | ||
746 | */ | ||
747 | _gnutls_str_cpy (tmp, sizeof (tmp), where); | ||
748 | _gnutls_str_cat (tmp, sizeof (tmp), ".type"); | ||
749 | |||
750 | result = asn1_write_value (asn1_struct, tmp, given_oid, 1); | ||
751 | if (result != ASN1_SUCCESS) | ||
752 | { | ||
753 | gnutls_assert (); | ||
754 | return _gnutls_asn2err (result); | ||
755 | } | ||
756 | |||
757 | return 0; | ||
758 | } | ||
759 | |||
760 | /* This will write the AttributeTypeAndValue field. The data must be already DER encoded. | ||
761 | * 'multi' must be zero if writing an AttributeTypeAndValue, and 1 if Attribute. | ||
762 | * In all cases only one value is written. | ||
763 | */ | ||
764 | int | ||
765 | _gnutls_x509_write_attribute (const char *given_oid, | ||
766 | ASN1_TYPE asn1_struct, const char *where, | ||
767 | const void *_data, int sizeof_data, int multi) | ||
768 | { | ||
769 | char tmp[128]; | ||
770 | int result; | ||
771 | |||
772 | /* write the data (value) | ||
773 | */ | ||
774 | |||
775 | _gnutls_str_cpy (tmp, sizeof (tmp), where); | ||
776 | _gnutls_str_cat (tmp, sizeof (tmp), ".value"); | ||
777 | |||
778 | if (multi != 0) | ||
779 | { /* if not writing an AttributeTypeAndValue, but an Attribute */ | ||
780 | _gnutls_str_cat (tmp, sizeof (tmp), "s"); /* values */ | ||
781 | |||
782 | result = asn1_write_value (asn1_struct, tmp, "NEW", 1); | ||
783 | if (result != ASN1_SUCCESS) | ||
784 | { | ||
785 | gnutls_assert (); | ||
786 | return _gnutls_asn2err (result); | ||
787 | } | ||
788 | |||
789 | _gnutls_str_cat (tmp, sizeof (tmp), ".?LAST"); | ||
790 | |||
791 | } | ||
792 | |||
793 | result = asn1_write_value (asn1_struct, tmp, _data, sizeof_data); | ||
794 | if (result < 0) | ||
795 | { | ||
796 | gnutls_assert (); | ||
797 | return _gnutls_asn2err (result); | ||
798 | } | ||
799 | |||
800 | /* write the type | ||
801 | */ | ||
802 | _gnutls_str_cpy (tmp, sizeof (tmp), where); | ||
803 | _gnutls_str_cat (tmp, sizeof (tmp), ".type"); | ||
804 | |||
805 | result = asn1_write_value (asn1_struct, tmp, given_oid, 1); | ||
806 | if (result != ASN1_SUCCESS) | ||
807 | { | ||
808 | gnutls_assert (); | ||
809 | return _gnutls_asn2err (result); | ||
810 | } | ||
811 | |||
812 | return 0; | ||
813 | } | ||
814 | |||
815 | |||
816 | /* Decodes an X.509 Attribute (if multi==1) or an AttributeTypeAndValue | ||
817 | * otherwise. | ||
818 | * | ||
819 | * octet_string should be non zero if we are to decode octet strings after | ||
820 | * decoding. | ||
821 | * | ||
822 | * The output is allocated and stored in value. | ||
823 | */ | ||
824 | int | ||
825 | _gnutls_x509_decode_and_read_attribute (ASN1_TYPE asn1_struct, | ||
826 | const char *where, char *oid, | ||
827 | int oid_size, gnutls_datum_t * value, | ||
828 | int multi, int octet_string) | ||
829 | { | ||
830 | char tmpbuffer[128]; | ||
831 | int len, result; | ||
832 | |||
833 | /* Read the OID | ||
834 | */ | ||
835 | _gnutls_str_cpy (tmpbuffer, sizeof (tmpbuffer), where); | ||
836 | _gnutls_str_cat (tmpbuffer, sizeof (tmpbuffer), ".type"); | ||
837 | |||
838 | len = oid_size - 1; | ||
839 | result = asn1_read_value (asn1_struct, tmpbuffer, oid, &len); | ||
840 | |||
841 | if (result != ASN1_SUCCESS) | ||
842 | { | ||
843 | gnutls_assert (); | ||
844 | result = _gnutls_asn2err (result); | ||
845 | return result; | ||
846 | } | ||
847 | |||
848 | /* Read the Value | ||
849 | */ | ||
850 | |||
851 | _gnutls_str_cpy (tmpbuffer, sizeof (tmpbuffer), where); | ||
852 | _gnutls_str_cat (tmpbuffer, sizeof (tmpbuffer), ".value"); | ||
853 | |||
854 | if (multi) | ||
855 | _gnutls_str_cat (tmpbuffer, sizeof (tmpbuffer), "s.?1"); /* .values.?1 */ | ||
856 | |||
857 | result = | ||
858 | _gnutls_x509_read_value (asn1_struct, tmpbuffer, value, octet_string); | ||
859 | if (result < 0) | ||
860 | { | ||
861 | gnutls_assert (); | ||
862 | return result; | ||
863 | } | ||
864 | |||
865 | return 0; | ||
866 | |||
867 | } | ||
868 | |||
869 | /* Sets an X509 DN in the asn1_struct, and puts the given OID in the DN. | ||
870 | * The input is assumed to be raw data. | ||
871 | * | ||
872 | * asn1_rdn_name must be a string in the form "tbsCertificate.issuer". | ||
873 | * That is to point before the rndSequence. | ||
874 | * | ||
875 | */ | ||
876 | int | ||
877 | _gnutls_x509_set_dn_oid (ASN1_TYPE asn1_struct, | ||
878 | const char *asn1_name, const char *given_oid, | ||
879 | int raw_flag, const char *name, int sizeof_name) | ||
880 | { | ||
881 | int result; | ||
882 | char tmp[MAX_NAME_SIZE], asn1_rdn_name[MAX_NAME_SIZE]; | ||
883 | |||
884 | if (sizeof_name == 0 || name == NULL) | ||
885 | { | ||
886 | gnutls_assert (); | ||
887 | return GNUTLS_E_INVALID_REQUEST; | ||
888 | } | ||
889 | |||
890 | /* create the rdnSequence | ||
891 | */ | ||
892 | result = asn1_write_value (asn1_struct, asn1_name, "rdnSequence", 1); | ||
893 | if (result != ASN1_SUCCESS) | ||
894 | { | ||
895 | gnutls_assert (); | ||
896 | return _gnutls_asn2err (result); | ||
897 | } | ||
898 | |||
899 | _gnutls_str_cpy (asn1_rdn_name, sizeof (asn1_rdn_name), asn1_name); | ||
900 | _gnutls_str_cat (asn1_rdn_name, sizeof (asn1_rdn_name), ".rdnSequence"); | ||
901 | |||
902 | /* create a new element | ||
903 | */ | ||
904 | result = asn1_write_value (asn1_struct, asn1_rdn_name, "NEW", 1); | ||
905 | if (result != ASN1_SUCCESS) | ||
906 | { | ||
907 | gnutls_assert (); | ||
908 | return _gnutls_asn2err (result); | ||
909 | } | ||
910 | |||
911 | _gnutls_str_cpy (tmp, sizeof (tmp), asn1_rdn_name); | ||
912 | _gnutls_str_cat (tmp, sizeof (tmp), ".?LAST"); | ||
913 | |||
914 | /* create the set with only one element | ||
915 | */ | ||
916 | result = asn1_write_value (asn1_struct, tmp, "NEW", 1); | ||
917 | if (result != ASN1_SUCCESS) | ||
918 | { | ||
919 | gnutls_assert (); | ||
920 | return _gnutls_asn2err (result); | ||
921 | } | ||
922 | |||
923 | |||
924 | /* Encode and write the data | ||
925 | */ | ||
926 | _gnutls_str_cpy (tmp, sizeof (tmp), asn1_rdn_name); | ||
927 | _gnutls_str_cat (tmp, sizeof (tmp), ".?LAST.?LAST"); | ||
928 | |||
929 | if (!raw_flag) | ||
930 | { | ||
931 | result = | ||
932 | _gnutls_x509_encode_and_write_attribute (given_oid, | ||
933 | asn1_struct, | ||
934 | tmp, name, sizeof_name, 0); | ||
935 | } | ||
936 | else | ||
937 | { | ||
938 | result = | ||
939 | _gnutls_x509_write_attribute (given_oid, asn1_struct, | ||
940 | tmp, name, sizeof_name, 0); | ||
941 | } | ||
942 | |||
943 | if (result < 0) | ||
944 | { | ||
945 | gnutls_assert (); | ||
946 | return result; | ||
947 | } | ||
948 | |||
949 | return 0; | ||
950 | } | ||
951 | |||
952 | |||
953 | /** | ||
954 | * gnutls_x509_rdn_get - This function parses an RDN sequence and returns a string | ||
955 | * @idn: should contain a DER encoded RDN sequence | ||
956 | * @buf: a pointer to a structure to hold the peer's name | ||
957 | * @sizeof_buf: holds the size of @buf | ||
958 | * | ||
959 | * This function will return the name of the given RDN sequence. The | ||
960 | * name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in | ||
961 | * RFC2253. | ||
962 | * | ||
963 | * If the provided buffer is not long enough, returns | ||
964 | * GNUTLS_E_SHORT_MEMORY_BUFFER and *sizeof_buf will be updated. On | ||
965 | * success 0 is returned. | ||
966 | * | ||
967 | **/ | ||
968 | int | ||
969 | gnutls_x509_rdn_get (const gnutls_datum_t * idn, | ||
970 | char *buf, size_t * sizeof_buf) | ||
971 | { | ||
972 | int result; | ||
973 | ASN1_TYPE dn = ASN1_TYPE_EMPTY; | ||
974 | |||
975 | if (sizeof_buf == 0) | ||
976 | { | ||
977 | gnutls_assert (); | ||
978 | return GNUTLS_E_INVALID_REQUEST; | ||
979 | } | ||
980 | |||
981 | if (buf) | ||
982 | buf[0] = 0; | ||
983 | |||
984 | |||
985 | if ((result = | ||
986 | asn1_create_element (_gnutls_get_pkix (), | ||
987 | "PKIX1.Name", &dn)) != ASN1_SUCCESS) | ||
988 | { | ||
989 | gnutls_assert (); | ||
990 | return _gnutls_asn2err (result); | ||
991 | } | ||
992 | |||
993 | result = asn1_der_decoding (&dn, idn->data, idn->size, NULL); | ||
994 | if (result != ASN1_SUCCESS) | ||
995 | { | ||
996 | /* couldn't decode DER */ | ||
997 | gnutls_assert (); | ||
998 | asn1_delete_structure (&dn); | ||
999 | return _gnutls_asn2err (result); | ||
1000 | } | ||
1001 | |||
1002 | result = _gnutls_x509_parse_dn (dn, "rdnSequence", buf, sizeof_buf); | ||
1003 | |||
1004 | asn1_delete_structure (&dn); | ||
1005 | return result; | ||
1006 | |||
1007 | } | ||
1008 | |||
1009 | /** | ||
1010 | * gnutls_x509_rdn_get_by_oid - This function parses an RDN sequence and returns a string | ||
1011 | * @idn: should contain a DER encoded RDN sequence | ||
1012 | * @oid: an Object Identifier | ||
1013 | * @indx: In case multiple same OIDs exist in the RDN indicates which | ||
1014 | * to send. Use 0 for the first one. | ||
1015 | * @raw_flag: If non zero then the raw DER data are returned. | ||
1016 | * @buf: a pointer to a structure to hold the peer's name | ||
1017 | * @sizeof_buf: holds the size of @buf | ||
1018 | * | ||
1019 | * This function will return the name of the given Object identifier, | ||
1020 | * of the RDN sequence. The name will be encoded using the rules | ||
1021 | * from RFC2253. | ||
1022 | * | ||
1023 | * Returns GNUTLS_E_SHORT_MEMORY_BUFFER and updates *sizeof_buf if | ||
1024 | * the provided buffer is not long enough, and 0 on success. | ||
1025 | * | ||
1026 | **/ | ||
1027 | int | ||
1028 | gnutls_x509_rdn_get_by_oid (const gnutls_datum_t * idn, const char *oid, | ||
1029 | int indx, unsigned int raw_flag, | ||
1030 | void *buf, size_t * sizeof_buf) | ||
1031 | { | ||
1032 | int result; | ||
1033 | ASN1_TYPE dn = ASN1_TYPE_EMPTY; | ||
1034 | |||
1035 | if (sizeof_buf == 0) | ||
1036 | { | ||
1037 | return GNUTLS_E_INVALID_REQUEST; | ||
1038 | } | ||
1039 | |||
1040 | if ((result = | ||
1041 | asn1_create_element (_gnutls_get_pkix (), | ||
1042 | "PKIX1.Name", &dn)) != ASN1_SUCCESS) | ||
1043 | { | ||
1044 | gnutls_assert (); | ||
1045 | return _gnutls_asn2err (result); | ||
1046 | } | ||
1047 | |||
1048 | result = asn1_der_decoding (&dn, idn->data, idn->size, NULL); | ||
1049 | if (result != ASN1_SUCCESS) | ||
1050 | { | ||
1051 | /* couldn't decode DER */ | ||
1052 | gnutls_assert (); | ||
1053 | asn1_delete_structure (&dn); | ||
1054 | return _gnutls_asn2err (result); | ||
1055 | } | ||
1056 | |||
1057 | result = | ||
1058 | _gnutls_x509_parse_dn_oid (dn, "rdnSequence", oid, indx, | ||
1059 | raw_flag, buf, sizeof_buf); | ||
1060 | |||
1061 | asn1_delete_structure (&dn); | ||
1062 | return result; | ||
1063 | |||
1064 | } | ||
1065 | |||
1066 | /** | ||
1067 | * gnutls_x509_rdn_get_oid - This function parses an RDN sequence and returns an OID. | ||
1068 | * @idn: should contain a DER encoded RDN sequence | ||
1069 | * @indx: Indicates which OID to return. Use 0 for the first one. | ||
1070 | * @oid: a pointer to a structure to hold the peer's name OID | ||
1071 | * @sizeof_oid: holds the size of @oid | ||
1072 | * | ||
1073 | * This function will return the specified Object identifier, of the | ||
1074 | * RDN sequence. | ||
1075 | * | ||
1076 | * Returns GNUTLS_E_SHORT_MEMORY_BUFFER and updates *sizeof_buf if | ||
1077 | * the provided buffer is not long enough, and 0 on success. | ||
1078 | * | ||
1079 | **/ | ||
1080 | int | ||
1081 | gnutls_x509_rdn_get_oid (const gnutls_datum_t * idn, | ||
1082 | int indx, void *buf, size_t * sizeof_buf) | ||
1083 | { | ||
1084 | int result; | ||
1085 | ASN1_TYPE dn = ASN1_TYPE_EMPTY; | ||
1086 | |||
1087 | if (sizeof_buf == 0) | ||
1088 | { | ||
1089 | return GNUTLS_E_INVALID_REQUEST; | ||
1090 | } | ||
1091 | |||
1092 | if ((result = | ||
1093 | asn1_create_element (_gnutls_get_pkix (), | ||
1094 | "PKIX1.Name", &dn)) != ASN1_SUCCESS) | ||
1095 | { | ||
1096 | gnutls_assert (); | ||
1097 | return _gnutls_asn2err (result); | ||
1098 | } | ||
1099 | |||
1100 | result = asn1_der_decoding (&dn, idn->data, idn->size, NULL); | ||
1101 | if (result != ASN1_SUCCESS) | ||
1102 | { | ||
1103 | /* couldn't decode DER */ | ||
1104 | gnutls_assert (); | ||
1105 | asn1_delete_structure (&dn); | ||
1106 | return _gnutls_asn2err (result); | ||
1107 | } | ||
1108 | |||
1109 | result = _gnutls_x509_get_dn_oid (dn, "rdnSequence", indx, buf, sizeof_buf); | ||
1110 | |||
1111 | asn1_delete_structure (&dn); | ||
1112 | return result; | ||
1113 | |||
1114 | } | ||
1115 | |||
1116 | /* | ||
1117 | * Compares the DER encoded part of a DN. | ||
1118 | * | ||
1119 | * FIXME: use a real DN comparison algorithm. | ||
1120 | * | ||
1121 | * Returns 1 if the DN's match and zero if they don't match. Otherwise | ||
1122 | * a negative value is returned to indicate error. | ||
1123 | */ | ||
1124 | int | ||
1125 | _gnutls_x509_compare_raw_dn (const gnutls_datum_t * dn1, | ||
1126 | const gnutls_datum_t * dn2) | ||
1127 | { | ||
1128 | |||
1129 | if (dn1->size != dn2->size) | ||
1130 | { | ||
1131 | gnutls_assert (); | ||
1132 | return 0; | ||
1133 | } | ||
1134 | if (memcmp (dn1->data, dn2->data, dn2->size) != 0) | ||
1135 | { | ||
1136 | gnutls_assert (); | ||
1137 | return 0; | ||
1138 | } | ||
1139 | return 1; /* they match */ | ||
1140 | } | ||
diff --git a/src/daemon/https/x509/dn.h b/src/daemon/https/x509/dn.h new file mode 100644 index 00000000..93a9262c --- /dev/null +++ b/src/daemon/https/x509/dn.h | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef DN_H | ||
26 | # define DN_H | ||
27 | |||
28 | /* Some OIDs usually found in Distinguished names | ||
29 | */ | ||
30 | #define OID_X520_COUNTRY_NAME "2.5.4.6" | ||
31 | #define OID_X520_ORGANIZATION_NAME "2.5.4.10" | ||
32 | #define OID_X520_ORGANIZATIONAL_UNIT_NAME "2.5.4.11" | ||
33 | #define OID_X520_COMMON_NAME "2.5.4.3" | ||
34 | #define OID_X520_LOCALITY_NAME "2.5.4.7" | ||
35 | #define OID_X520_STATE_OR_PROVINCE_NAME "2.5.4.8" | ||
36 | #define OID_LDAP_DC "0.9.2342.19200300.100.1.25" | ||
37 | #define OID_LDAP_UID "0.9.2342.19200300.100.1.1" | ||
38 | #define OID_PKCS9_EMAIL "1.2.840.113549.1.9.1" | ||
39 | |||
40 | int _gnutls_x509_parse_dn (ASN1_TYPE asn1_struct, | ||
41 | const char *asn1_rdn_name, char *buf, | ||
42 | size_t * sizeof_buf); | ||
43 | |||
44 | int _gnutls_x509_parse_dn_oid (ASN1_TYPE asn1_struct, | ||
45 | const char *asn1_rdn_name, const char *oid, | ||
46 | int indx, unsigned int raw_flag, void *buf, | ||
47 | size_t * sizeof_buf); | ||
48 | |||
49 | int _gnutls_x509_set_dn_oid (ASN1_TYPE asn1_struct, | ||
50 | const char *asn1_rdn_name, const char *oid, | ||
51 | int raw_flag, const char *name, int sizeof_name); | ||
52 | |||
53 | int _gnutls_x509_get_dn_oid (ASN1_TYPE asn1_struct, | ||
54 | const char *asn1_rdn_name, | ||
55 | int indx, void *_oid, size_t * sizeof_oid); | ||
56 | |||
57 | |||
58 | #endif | ||
diff --git a/src/daemon/https/x509/dsa.c b/src/daemon/https/x509/dsa.c new file mode 100644 index 00000000..af403911 --- /dev/null +++ b/src/daemon/https/x509/dsa.c | |||
@@ -0,0 +1,142 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | /* This file contains code for DSA keys. | ||
26 | */ | ||
27 | |||
28 | #include <gnutls_int.h> | ||
29 | #include <gnutls_errors.h> | ||
30 | #include <gnutls_datum.h> | ||
31 | #include <debug.h> | ||
32 | |||
33 | /* resarr will contain: p(0), q(1), g(2), y(3), x(4). | ||
34 | */ | ||
35 | int | ||
36 | _gnutls_dsa_generate_params (mpi_t * resarr, int *resarr_len, int bits) | ||
37 | { | ||
38 | |||
39 | int ret; | ||
40 | gcry_sexp_t parms, key, list; | ||
41 | |||
42 | /* FIXME: Remove me once we depend on 1.3.1 */ | ||
43 | if (bits > 1024 && gcry_check_version ("1.3.1") == NULL) | ||
44 | { | ||
45 | gnutls_assert (); | ||
46 | return GNUTLS_E_INVALID_REQUEST; | ||
47 | } | ||
48 | |||
49 | if (bits < 512) | ||
50 | { | ||
51 | gnutls_assert (); | ||
52 | return GNUTLS_E_INVALID_REQUEST; | ||
53 | } | ||
54 | |||
55 | ret = gcry_sexp_build (&parms, NULL, "(genkey(dsa(nbits %d)))", bits); | ||
56 | if (ret != 0) | ||
57 | { | ||
58 | gnutls_assert (); | ||
59 | return GNUTLS_E_INTERNAL_ERROR; | ||
60 | } | ||
61 | |||
62 | /* generate the DSA key | ||
63 | */ | ||
64 | ret = gcry_pk_genkey (&key, parms); | ||
65 | gcry_sexp_release (parms); | ||
66 | |||
67 | if (ret != 0) | ||
68 | { | ||
69 | gnutls_assert (); | ||
70 | return GNUTLS_E_INTERNAL_ERROR; | ||
71 | } | ||
72 | |||
73 | list = gcry_sexp_find_token (key, "p", 0); | ||
74 | if (list == NULL) | ||
75 | { | ||
76 | gnutls_assert (); | ||
77 | gcry_sexp_release (key); | ||
78 | return GNUTLS_E_INTERNAL_ERROR; | ||
79 | } | ||
80 | |||
81 | resarr[0] = gcry_sexp_nth_mpi (list, 1, 0); | ||
82 | gcry_sexp_release (list); | ||
83 | |||
84 | list = gcry_sexp_find_token (key, "q", 0); | ||
85 | if (list == NULL) | ||
86 | { | ||
87 | gnutls_assert (); | ||
88 | gcry_sexp_release (key); | ||
89 | return GNUTLS_E_INTERNAL_ERROR; | ||
90 | } | ||
91 | |||
92 | resarr[1] = gcry_sexp_nth_mpi (list, 1, 0); | ||
93 | gcry_sexp_release (list); | ||
94 | |||
95 | list = gcry_sexp_find_token (key, "g", 0); | ||
96 | if (list == NULL) | ||
97 | { | ||
98 | gnutls_assert (); | ||
99 | gcry_sexp_release (key); | ||
100 | return GNUTLS_E_INTERNAL_ERROR; | ||
101 | } | ||
102 | |||
103 | resarr[2] = gcry_sexp_nth_mpi (list, 1, 0); | ||
104 | gcry_sexp_release (list); | ||
105 | |||
106 | list = gcry_sexp_find_token (key, "y", 0); | ||
107 | if (list == NULL) | ||
108 | { | ||
109 | gnutls_assert (); | ||
110 | gcry_sexp_release (key); | ||
111 | return GNUTLS_E_INTERNAL_ERROR; | ||
112 | } | ||
113 | |||
114 | resarr[3] = gcry_sexp_nth_mpi (list, 1, 0); | ||
115 | gcry_sexp_release (list); | ||
116 | |||
117 | |||
118 | list = gcry_sexp_find_token (key, "x", 0); | ||
119 | if (list == NULL) | ||
120 | { | ||
121 | gnutls_assert (); | ||
122 | gcry_sexp_release (key); | ||
123 | return GNUTLS_E_INTERNAL_ERROR; | ||
124 | } | ||
125 | |||
126 | resarr[4] = gcry_sexp_nth_mpi (list, 1, 0); | ||
127 | gcry_sexp_release (list); | ||
128 | |||
129 | |||
130 | gcry_sexp_release (key); | ||
131 | |||
132 | _gnutls_dump_mpi ("p: ", resarr[0]); | ||
133 | _gnutls_dump_mpi ("q: ", resarr[1]); | ||
134 | _gnutls_dump_mpi ("g: ", resarr[2]); | ||
135 | _gnutls_dump_mpi ("y: ", resarr[3]); | ||
136 | _gnutls_dump_mpi ("x: ", resarr[4]); | ||
137 | |||
138 | *resarr_len = 5; | ||
139 | |||
140 | return 0; | ||
141 | |||
142 | } | ||
diff --git a/src/daemon/https/x509/dsa.h b/src/daemon/https/x509/dsa.h new file mode 100644 index 00000000..5489ffa3 --- /dev/null +++ b/src/daemon/https/x509/dsa.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | int _gnutls_dsa_generate_params (mpi_t * resarr, int *resarr_len, int bits); | ||
diff --git a/src/daemon/https/x509/extensions.c b/src/daemon/https/x509/extensions.c new file mode 100644 index 00000000..98379add --- /dev/null +++ b/src/daemon/https/x509/extensions.c | |||
@@ -0,0 +1,1095 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | /* Functions that relate to the X.509 extension parsing. | ||
26 | */ | ||
27 | |||
28 | #include <gnutls_int.h> | ||
29 | #include <gnutls_errors.h> | ||
30 | #include <gnutls_global.h> | ||
31 | #include <mpi.h> | ||
32 | #include <libtasn1.h> | ||
33 | #include <common.h> | ||
34 | #include <x509.h> | ||
35 | #include <extensions.h> | ||
36 | #include <gnutls_datum.h> | ||
37 | |||
38 | /* This function will attempt to return the requested extension found in | ||
39 | * the given X509v3 certificate. The return value is allocated and stored into | ||
40 | * ret. | ||
41 | * | ||
42 | * Critical will be either 0 or 1. | ||
43 | * | ||
44 | * If the extension does not exist, GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will | ||
45 | * be returned. | ||
46 | */ | ||
47 | int | ||
48 | _gnutls_x509_crt_get_extension (gnutls_x509_crt_t cert, | ||
49 | const char *extension_id, int indx, | ||
50 | gnutls_datum_t * ret, unsigned int *_critical) | ||
51 | { | ||
52 | int k, result, len; | ||
53 | char name[MAX_NAME_SIZE], name2[MAX_NAME_SIZE]; | ||
54 | char str[1024]; | ||
55 | char str_critical[10]; | ||
56 | int critical = 0; | ||
57 | char extnID[128]; | ||
58 | gnutls_datum_t value; | ||
59 | int indx_counter = 0; | ||
60 | |||
61 | ret->data = NULL; | ||
62 | ret->size = 0; | ||
63 | |||
64 | k = 0; | ||
65 | do | ||
66 | { | ||
67 | k++; | ||
68 | |||
69 | snprintf (name, sizeof (name), "tbsCertificate.extensions.?%u", k); | ||
70 | |||
71 | len = sizeof (str) - 1; | ||
72 | result = asn1_read_value (cert->cert, name, str, &len); | ||
73 | |||
74 | /* move to next | ||
75 | */ | ||
76 | |||
77 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
78 | { | ||
79 | break; | ||
80 | } | ||
81 | |||
82 | do | ||
83 | { | ||
84 | |||
85 | _gnutls_str_cpy (name2, sizeof (name2), name); | ||
86 | _gnutls_str_cat (name2, sizeof (name2), ".extnID"); | ||
87 | |||
88 | len = sizeof (extnID) - 1; | ||
89 | result = asn1_read_value (cert->cert, name2, extnID, &len); | ||
90 | |||
91 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
92 | { | ||
93 | gnutls_assert (); | ||
94 | break; | ||
95 | } | ||
96 | else if (result != ASN1_SUCCESS) | ||
97 | { | ||
98 | gnutls_assert (); | ||
99 | return _gnutls_asn2err (result); | ||
100 | } | ||
101 | |||
102 | /* Handle Extension | ||
103 | */ | ||
104 | if (strcmp (extnID, extension_id) == 0 && indx == indx_counter++) | ||
105 | { | ||
106 | /* extension was found | ||
107 | */ | ||
108 | |||
109 | /* read the critical status. | ||
110 | */ | ||
111 | _gnutls_str_cpy (name2, sizeof (name2), name); | ||
112 | _gnutls_str_cat (name2, sizeof (name2), ".critical"); | ||
113 | |||
114 | len = sizeof (str_critical); | ||
115 | result = | ||
116 | asn1_read_value (cert->cert, name2, str_critical, &len); | ||
117 | |||
118 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
119 | { | ||
120 | gnutls_assert (); | ||
121 | break; | ||
122 | } | ||
123 | else if (result != ASN1_SUCCESS) | ||
124 | { | ||
125 | gnutls_assert (); | ||
126 | return _gnutls_asn2err (result); | ||
127 | } | ||
128 | |||
129 | if (str_critical[0] == 'T') | ||
130 | critical = 1; | ||
131 | else | ||
132 | critical = 0; | ||
133 | |||
134 | /* read the value. | ||
135 | */ | ||
136 | _gnutls_str_cpy (name2, sizeof (name2), name); | ||
137 | _gnutls_str_cat (name2, sizeof (name2), ".extnValue"); | ||
138 | |||
139 | result = _gnutls_x509_read_value (cert->cert, name2, &value, 0); | ||
140 | if (result < 0) | ||
141 | { | ||
142 | gnutls_assert (); | ||
143 | return result; | ||
144 | } | ||
145 | |||
146 | ret->data = value.data; | ||
147 | ret->size = value.size; | ||
148 | |||
149 | if (_critical) | ||
150 | *_critical = critical; | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | |||
156 | } | ||
157 | while (0); | ||
158 | } | ||
159 | while (1); | ||
160 | |||
161 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
162 | { | ||
163 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
164 | } | ||
165 | else | ||
166 | { | ||
167 | gnutls_assert (); | ||
168 | return _gnutls_asn2err (result); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | /* This function will attempt to return the requested extension OID found in | ||
173 | * the given X509v3 certificate. | ||
174 | * | ||
175 | * If you have passed the last extension, GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will | ||
176 | * be returned. | ||
177 | */ | ||
178 | int | ||
179 | _gnutls_x509_crt_get_extension_oid (gnutls_x509_crt_t cert, | ||
180 | int indx, void *oid, size_t * sizeof_oid) | ||
181 | { | ||
182 | int k, result, len; | ||
183 | char name[MAX_NAME_SIZE], name2[MAX_NAME_SIZE]; | ||
184 | char str[1024]; | ||
185 | char extnID[128]; | ||
186 | int indx_counter = 0; | ||
187 | |||
188 | k = 0; | ||
189 | do | ||
190 | { | ||
191 | k++; | ||
192 | |||
193 | snprintf (name, sizeof (name), "tbsCertificate.extensions.?%u", k); | ||
194 | |||
195 | len = sizeof (str) - 1; | ||
196 | result = asn1_read_value (cert->cert, name, str, &len); | ||
197 | |||
198 | /* move to next | ||
199 | */ | ||
200 | |||
201 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
202 | { | ||
203 | break; | ||
204 | } | ||
205 | |||
206 | do | ||
207 | { | ||
208 | |||
209 | _gnutls_str_cpy (name2, sizeof (name2), name); | ||
210 | _gnutls_str_cat (name2, sizeof (name2), ".extnID"); | ||
211 | |||
212 | len = sizeof (extnID) - 1; | ||
213 | result = asn1_read_value (cert->cert, name2, extnID, &len); | ||
214 | |||
215 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
216 | { | ||
217 | gnutls_assert (); | ||
218 | break; | ||
219 | } | ||
220 | else if (result != ASN1_SUCCESS) | ||
221 | { | ||
222 | gnutls_assert (); | ||
223 | return _gnutls_asn2err (result); | ||
224 | } | ||
225 | |||
226 | /* Handle Extension | ||
227 | */ | ||
228 | if (indx == indx_counter++) | ||
229 | { | ||
230 | len = strlen (extnID) + 1; | ||
231 | |||
232 | if (*sizeof_oid < (unsigned) len) | ||
233 | { | ||
234 | *sizeof_oid = len; | ||
235 | gnutls_assert (); | ||
236 | return GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
237 | } | ||
238 | |||
239 | memcpy (oid, extnID, len); | ||
240 | *sizeof_oid = len - 1; | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | |||
246 | } | ||
247 | while (0); | ||
248 | } | ||
249 | while (1); | ||
250 | |||
251 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
252 | { | ||
253 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
254 | } | ||
255 | else | ||
256 | { | ||
257 | gnutls_assert (); | ||
258 | return _gnutls_asn2err (result); | ||
259 | } | ||
260 | } | ||
261 | |||
262 | /* This function will attempt to set the requested extension in | ||
263 | * the given X509v3 certificate. | ||
264 | * | ||
265 | * Critical will be either 0 or 1. | ||
266 | */ | ||
267 | static int | ||
268 | set_extension (ASN1_TYPE asn, const char *extension_id, | ||
269 | const gnutls_datum_t * ext_data, unsigned int critical) | ||
270 | { | ||
271 | int result; | ||
272 | const char *str; | ||
273 | |||
274 | /* Add a new extension in the list. | ||
275 | */ | ||
276 | result = asn1_write_value (asn, "tbsCertificate.extensions", "NEW", 1); | ||
277 | if (result != ASN1_SUCCESS) | ||
278 | { | ||
279 | gnutls_assert (); | ||
280 | return _gnutls_asn2err (result); | ||
281 | } | ||
282 | |||
283 | result = | ||
284 | asn1_write_value (asn, "tbsCertificate.extensions.?LAST.extnID", | ||
285 | extension_id, 1); | ||
286 | if (result != ASN1_SUCCESS) | ||
287 | { | ||
288 | gnutls_assert (); | ||
289 | return _gnutls_asn2err (result); | ||
290 | } | ||
291 | |||
292 | if (critical == 0) | ||
293 | str = "FALSE"; | ||
294 | else | ||
295 | str = "TRUE"; | ||
296 | |||
297 | |||
298 | result = | ||
299 | asn1_write_value (asn, "tbsCertificate.extensions.?LAST.critical", | ||
300 | str, 1); | ||
301 | if (result != ASN1_SUCCESS) | ||
302 | { | ||
303 | gnutls_assert (); | ||
304 | return _gnutls_asn2err (result); | ||
305 | } | ||
306 | |||
307 | result = | ||
308 | _gnutls_x509_write_value (asn, | ||
309 | "tbsCertificate.extensions.?LAST.extnValue", | ||
310 | ext_data, 0); | ||
311 | if (result < 0) | ||
312 | { | ||
313 | gnutls_assert (); | ||
314 | return result; | ||
315 | } | ||
316 | |||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | /* Overwrite the given extension (using the index) | ||
321 | * index here starts from one. | ||
322 | */ | ||
323 | static int | ||
324 | overwrite_extension (ASN1_TYPE asn, unsigned int indx, | ||
325 | const gnutls_datum_t * ext_data, unsigned int critical) | ||
326 | { | ||
327 | char name[MAX_NAME_SIZE], name2[MAX_NAME_SIZE]; | ||
328 | const char *str; | ||
329 | int result; | ||
330 | |||
331 | snprintf (name, sizeof (name), "tbsCertificate.extensions.?%u", indx); | ||
332 | |||
333 | if (critical == 0) | ||
334 | str = "FALSE"; | ||
335 | else | ||
336 | str = "TRUE"; | ||
337 | |||
338 | _gnutls_str_cpy (name2, sizeof (name2), name); | ||
339 | _gnutls_str_cat (name2, sizeof (name2), ".critical"); | ||
340 | |||
341 | result = asn1_write_value (asn, name2, str, 1); | ||
342 | if (result != ASN1_SUCCESS) | ||
343 | { | ||
344 | gnutls_assert (); | ||
345 | return _gnutls_asn2err (result); | ||
346 | } | ||
347 | |||
348 | _gnutls_str_cpy (name2, sizeof (name2), name); | ||
349 | _gnutls_str_cat (name2, sizeof (name2), ".extnValue"); | ||
350 | |||
351 | result = _gnutls_x509_write_value (asn, name2, ext_data, 0); | ||
352 | if (result < 0) | ||
353 | { | ||
354 | gnutls_assert (); | ||
355 | return result; | ||
356 | } | ||
357 | |||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | /* This function will attempt to overwrite the requested extension with | ||
362 | * the given one. | ||
363 | * | ||
364 | * Critical will be either 0 or 1. | ||
365 | */ | ||
366 | int | ||
367 | _gnutls_x509_crt_set_extension (gnutls_x509_crt_t cert, | ||
368 | const char *ext_id, | ||
369 | const gnutls_datum_t * ext_data, | ||
370 | unsigned int critical) | ||
371 | { | ||
372 | int result; | ||
373 | int k, len; | ||
374 | char name[MAX_NAME_SIZE], name2[MAX_NAME_SIZE]; | ||
375 | char extnID[128]; | ||
376 | |||
377 | /* Find the index of the given extension. | ||
378 | */ | ||
379 | k = 0; | ||
380 | do | ||
381 | { | ||
382 | k++; | ||
383 | |||
384 | snprintf (name, sizeof (name), "tbsCertificate.extensions.?%u", k); | ||
385 | |||
386 | len = sizeof (extnID) - 1; | ||
387 | result = asn1_read_value (cert->cert, name, extnID, &len); | ||
388 | |||
389 | /* move to next | ||
390 | */ | ||
391 | |||
392 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
393 | { | ||
394 | break; | ||
395 | } | ||
396 | |||
397 | do | ||
398 | { | ||
399 | |||
400 | _gnutls_str_cpy (name2, sizeof (name2), name); | ||
401 | _gnutls_str_cat (name2, sizeof (name2), ".extnID"); | ||
402 | |||
403 | len = sizeof (extnID) - 1; | ||
404 | result = asn1_read_value (cert->cert, name2, extnID, &len); | ||
405 | |||
406 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
407 | { | ||
408 | gnutls_assert (); | ||
409 | break; | ||
410 | } | ||
411 | else if (result != ASN1_SUCCESS) | ||
412 | { | ||
413 | gnutls_assert (); | ||
414 | return _gnutls_asn2err (result); | ||
415 | } | ||
416 | |||
417 | /* Handle Extension | ||
418 | */ | ||
419 | if (strcmp (extnID, ext_id) == 0) | ||
420 | { | ||
421 | /* extension was found | ||
422 | */ | ||
423 | return overwrite_extension (cert->cert, k, ext_data, critical); | ||
424 | } | ||
425 | |||
426 | |||
427 | } | ||
428 | while (0); | ||
429 | } | ||
430 | while (1); | ||
431 | |||
432 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
433 | { | ||
434 | return set_extension (cert->cert, ext_id, ext_data, critical); | ||
435 | } | ||
436 | else | ||
437 | { | ||
438 | gnutls_assert (); | ||
439 | return _gnutls_asn2err (result); | ||
440 | } | ||
441 | |||
442 | |||
443 | return 0; | ||
444 | } | ||
445 | |||
446 | |||
447 | /* Here we only extract the KeyUsage field, from the DER encoded | ||
448 | * extension. | ||
449 | */ | ||
450 | int | ||
451 | _gnutls_x509_ext_extract_keyUsage (uint16_t * keyUsage, | ||
452 | opaque * extnValue, int extnValueLen) | ||
453 | { | ||
454 | ASN1_TYPE ext = ASN1_TYPE_EMPTY; | ||
455 | int len, result; | ||
456 | uint8_t str[2]; | ||
457 | |||
458 | str[0] = str[1] = 0; | ||
459 | *keyUsage = 0; | ||
460 | |||
461 | if ((result = asn1_create_element | ||
462 | (_gnutls_get_pkix (), "PKIX1.KeyUsage", &ext)) != ASN1_SUCCESS) | ||
463 | { | ||
464 | gnutls_assert (); | ||
465 | return _gnutls_asn2err (result); | ||
466 | } | ||
467 | |||
468 | result = asn1_der_decoding (&ext, extnValue, extnValueLen, NULL); | ||
469 | |||
470 | if (result != ASN1_SUCCESS) | ||
471 | { | ||
472 | gnutls_assert (); | ||
473 | asn1_delete_structure (&ext); | ||
474 | return _gnutls_asn2err (result); | ||
475 | } | ||
476 | |||
477 | len = sizeof (str); | ||
478 | result = asn1_read_value (ext, "", str, &len); | ||
479 | if (result != ASN1_SUCCESS) | ||
480 | { | ||
481 | gnutls_assert (); | ||
482 | asn1_delete_structure (&ext); | ||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | *keyUsage = str[0] | (str[1] << 8); | ||
487 | |||
488 | asn1_delete_structure (&ext); | ||
489 | |||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | /* extract the basicConstraints from the DER encoded extension | ||
494 | */ | ||
495 | int | ||
496 | _gnutls_x509_ext_extract_basicConstraints (int *CA, | ||
497 | int *pathLenConstraint, | ||
498 | opaque * extnValue, | ||
499 | int extnValueLen) | ||
500 | { | ||
501 | ASN1_TYPE ext = ASN1_TYPE_EMPTY; | ||
502 | char str[128]; | ||
503 | int len, result; | ||
504 | |||
505 | if ((result = asn1_create_element | ||
506 | (_gnutls_get_pkix (), "PKIX1.BasicConstraints", &ext)) != ASN1_SUCCESS) | ||
507 | { | ||
508 | gnutls_assert (); | ||
509 | return _gnutls_asn2err (result); | ||
510 | } | ||
511 | |||
512 | result = asn1_der_decoding (&ext, extnValue, extnValueLen, NULL); | ||
513 | if (result != ASN1_SUCCESS) | ||
514 | { | ||
515 | gnutls_assert (); | ||
516 | asn1_delete_structure (&ext); | ||
517 | return _gnutls_asn2err (result); | ||
518 | } | ||
519 | |||
520 | if (pathLenConstraint) | ||
521 | { | ||
522 | result = _gnutls_x509_read_uint (ext, "pathLenConstraint", | ||
523 | pathLenConstraint); | ||
524 | if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) | ||
525 | *pathLenConstraint = -1; | ||
526 | else if (result != GNUTLS_E_SUCCESS) | ||
527 | { | ||
528 | gnutls_assert (); | ||
529 | asn1_delete_structure (&ext); | ||
530 | return _gnutls_asn2err (result); | ||
531 | } | ||
532 | } | ||
533 | |||
534 | /* the default value of cA is false. | ||
535 | */ | ||
536 | len = sizeof (str) - 1; | ||
537 | result = asn1_read_value (ext, "cA", str, &len); | ||
538 | if (result == ASN1_SUCCESS && strcmp (str, "TRUE") == 0) | ||
539 | *CA = 1; | ||
540 | else | ||
541 | *CA = 0; | ||
542 | |||
543 | asn1_delete_structure (&ext); | ||
544 | |||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | /* generate the basicConstraints in a DER encoded extension | ||
549 | * Use 0 or 1 (TRUE) for CA. | ||
550 | * Use negative values for pathLenConstraint to indicate that the field | ||
551 | * should not be present, >= 0 to indicate set values. | ||
552 | */ | ||
553 | int | ||
554 | _gnutls_x509_ext_gen_basicConstraints (int CA, | ||
555 | int pathLenConstraint, | ||
556 | gnutls_datum_t * der_ext) | ||
557 | { | ||
558 | ASN1_TYPE ext = ASN1_TYPE_EMPTY; | ||
559 | const char *str; | ||
560 | int result; | ||
561 | |||
562 | if (CA == 0) | ||
563 | str = "FALSE"; | ||
564 | else | ||
565 | str = "TRUE"; | ||
566 | |||
567 | result = | ||
568 | asn1_create_element (_gnutls_get_pkix (), "PKIX1.BasicConstraints", &ext); | ||
569 | if (result != ASN1_SUCCESS) | ||
570 | { | ||
571 | gnutls_assert (); | ||
572 | return _gnutls_asn2err (result); | ||
573 | } | ||
574 | |||
575 | result = asn1_write_value (ext, "cA", str, 1); | ||
576 | if (result != ASN1_SUCCESS) | ||
577 | { | ||
578 | gnutls_assert (); | ||
579 | asn1_delete_structure (&ext); | ||
580 | return _gnutls_asn2err (result); | ||
581 | } | ||
582 | |||
583 | if (pathLenConstraint < 0) | ||
584 | { | ||
585 | result = asn1_write_value (ext, "pathLenConstraint", NULL, 0); | ||
586 | if (result < 0) | ||
587 | result = _gnutls_asn2err (result); | ||
588 | } | ||
589 | else | ||
590 | result = _gnutls_x509_write_uint32 (ext, "pathLenConstraint", | ||
591 | pathLenConstraint); | ||
592 | if (result < 0) | ||
593 | { | ||
594 | gnutls_assert (); | ||
595 | asn1_delete_structure (&ext); | ||
596 | return result; | ||
597 | } | ||
598 | |||
599 | result = _gnutls_x509_der_encode (ext, "", der_ext, 0); | ||
600 | |||
601 | asn1_delete_structure (&ext); | ||
602 | |||
603 | if (result < 0) | ||
604 | { | ||
605 | gnutls_assert (); | ||
606 | return result; | ||
607 | } | ||
608 | |||
609 | return 0; | ||
610 | } | ||
611 | |||
612 | /* generate the keyUsage in a DER encoded extension | ||
613 | * Use an ORed SEQUENCE of GNUTLS_KEY_* for usage. | ||
614 | */ | ||
615 | int | ||
616 | _gnutls_x509_ext_gen_keyUsage (uint16_t usage, gnutls_datum_t * der_ext) | ||
617 | { | ||
618 | ASN1_TYPE ext = ASN1_TYPE_EMPTY; | ||
619 | int result; | ||
620 | uint8_t str[2]; | ||
621 | |||
622 | result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.KeyUsage", &ext); | ||
623 | if (result != ASN1_SUCCESS) | ||
624 | { | ||
625 | gnutls_assert (); | ||
626 | return _gnutls_asn2err (result); | ||
627 | } | ||
628 | |||
629 | str[0] = usage & 0xff; | ||
630 | str[1] = usage >> 8; | ||
631 | |||
632 | result = asn1_write_value (ext, "", str, 9); | ||
633 | if (result != ASN1_SUCCESS) | ||
634 | { | ||
635 | gnutls_assert (); | ||
636 | asn1_delete_structure (&ext); | ||
637 | return _gnutls_asn2err (result); | ||
638 | } | ||
639 | |||
640 | result = _gnutls_x509_der_encode (ext, "", der_ext, 0); | ||
641 | |||
642 | asn1_delete_structure (&ext); | ||
643 | |||
644 | if (result < 0) | ||
645 | { | ||
646 | gnutls_assert (); | ||
647 | return result; | ||
648 | } | ||
649 | |||
650 | return 0; | ||
651 | } | ||
652 | |||
653 | static int | ||
654 | write_new_general_name (ASN1_TYPE ext, const char *ext_name, | ||
655 | gnutls_x509_subject_alt_name_t type, | ||
656 | const char *data_string) | ||
657 | { | ||
658 | const char *str; | ||
659 | int result; | ||
660 | char name[128]; | ||
661 | |||
662 | result = asn1_write_value (ext, ext_name, "NEW", 1); | ||
663 | if (result != ASN1_SUCCESS) | ||
664 | { | ||
665 | gnutls_assert (); | ||
666 | return _gnutls_asn2err (result); | ||
667 | } | ||
668 | |||
669 | switch (type) | ||
670 | { | ||
671 | case GNUTLS_SAN_DNSNAME: | ||
672 | str = "dNSName"; | ||
673 | break; | ||
674 | case GNUTLS_SAN_RFC822NAME: | ||
675 | str = "rfc822Name"; | ||
676 | break; | ||
677 | case GNUTLS_SAN_URI: | ||
678 | str = "uniformResourceIdentifier"; | ||
679 | break; | ||
680 | case GNUTLS_SAN_IPADDRESS: | ||
681 | str = "iPAddress"; | ||
682 | break; | ||
683 | default: | ||
684 | gnutls_assert (); | ||
685 | return GNUTLS_E_INTERNAL_ERROR; | ||
686 | } | ||
687 | |||
688 | if (ext_name[0] == 0) | ||
689 | { /* no dot */ | ||
690 | _gnutls_str_cpy (name, sizeof (name), "?LAST"); | ||
691 | } | ||
692 | else | ||
693 | { | ||
694 | _gnutls_str_cpy (name, sizeof (name), ext_name); | ||
695 | _gnutls_str_cat (name, sizeof (name), ".?LAST"); | ||
696 | } | ||
697 | |||
698 | result = asn1_write_value (ext, name, str, 1); | ||
699 | if (result != ASN1_SUCCESS) | ||
700 | { | ||
701 | gnutls_assert (); | ||
702 | return _gnutls_asn2err (result); | ||
703 | } | ||
704 | |||
705 | _gnutls_str_cat (name, sizeof (name), "."); | ||
706 | _gnutls_str_cat (name, sizeof (name), str); | ||
707 | |||
708 | result = asn1_write_value (ext, name, data_string, strlen (data_string)); | ||
709 | if (result != ASN1_SUCCESS) | ||
710 | { | ||
711 | gnutls_assert (); | ||
712 | asn1_delete_structure (&ext); | ||
713 | return _gnutls_asn2err (result); | ||
714 | } | ||
715 | |||
716 | return 0; | ||
717 | } | ||
718 | |||
719 | /* Convert the given name to GeneralNames in a DER encoded extension. | ||
720 | * This is the same as subject alternative name. | ||
721 | */ | ||
722 | int | ||
723 | _gnutls_x509_ext_gen_subject_alt_name (gnutls_x509_subject_alt_name_t | ||
724 | type, const char *data_string, | ||
725 | gnutls_datum_t * der_ext) | ||
726 | { | ||
727 | ASN1_TYPE ext = ASN1_TYPE_EMPTY; | ||
728 | int result; | ||
729 | |||
730 | result = | ||
731 | asn1_create_element (_gnutls_get_pkix (), "PKIX1.GeneralNames", &ext); | ||
732 | if (result != ASN1_SUCCESS) | ||
733 | { | ||
734 | gnutls_assert (); | ||
735 | return _gnutls_asn2err (result); | ||
736 | } | ||
737 | |||
738 | result = write_new_general_name (ext, "", type, data_string); | ||
739 | if (result < 0) | ||
740 | { | ||
741 | gnutls_assert (); | ||
742 | asn1_delete_structure (&ext); | ||
743 | return result; | ||
744 | } | ||
745 | |||
746 | result = _gnutls_x509_der_encode (ext, "", der_ext, 0); | ||
747 | |||
748 | asn1_delete_structure (&ext); | ||
749 | |||
750 | if (result < 0) | ||
751 | { | ||
752 | gnutls_assert (); | ||
753 | return result; | ||
754 | } | ||
755 | |||
756 | return 0; | ||
757 | } | ||
758 | |||
759 | /* generate the SubjectKeyID in a DER encoded extension | ||
760 | */ | ||
761 | int | ||
762 | _gnutls_x509_ext_gen_key_id (const void *id, size_t id_size, | ||
763 | gnutls_datum_t * der_ext) | ||
764 | { | ||
765 | ASN1_TYPE ext = ASN1_TYPE_EMPTY; | ||
766 | int result; | ||
767 | |||
768 | result = | ||
769 | asn1_create_element (_gnutls_get_pkix (), | ||
770 | "PKIX1.SubjectKeyIdentifier", &ext); | ||
771 | if (result != ASN1_SUCCESS) | ||
772 | { | ||
773 | gnutls_assert (); | ||
774 | return _gnutls_asn2err (result); | ||
775 | } | ||
776 | |||
777 | result = asn1_write_value (ext, "", id, id_size); | ||
778 | if (result != ASN1_SUCCESS) | ||
779 | { | ||
780 | gnutls_assert (); | ||
781 | asn1_delete_structure (&ext); | ||
782 | return _gnutls_asn2err (result); | ||
783 | } | ||
784 | |||
785 | result = _gnutls_x509_der_encode (ext, "", der_ext, 0); | ||
786 | |||
787 | asn1_delete_structure (&ext); | ||
788 | |||
789 | if (result < 0) | ||
790 | { | ||
791 | gnutls_assert (); | ||
792 | return result; | ||
793 | } | ||
794 | |||
795 | return 0; | ||
796 | } | ||
797 | |||
798 | /* generate the AuthorityKeyID in a DER encoded extension | ||
799 | */ | ||
800 | int | ||
801 | _gnutls_x509_ext_gen_auth_key_id (const void *id, size_t id_size, | ||
802 | gnutls_datum_t * der_ext) | ||
803 | { | ||
804 | ASN1_TYPE ext = ASN1_TYPE_EMPTY; | ||
805 | int result; | ||
806 | |||
807 | result = | ||
808 | asn1_create_element (_gnutls_get_pkix (), | ||
809 | "PKIX1.AuthorityKeyIdentifier", &ext); | ||
810 | if (result != ASN1_SUCCESS) | ||
811 | { | ||
812 | gnutls_assert (); | ||
813 | return _gnutls_asn2err (result); | ||
814 | } | ||
815 | |||
816 | result = asn1_write_value (ext, "keyIdentifier", id, id_size); | ||
817 | if (result != ASN1_SUCCESS) | ||
818 | { | ||
819 | gnutls_assert (); | ||
820 | asn1_delete_structure (&ext); | ||
821 | return _gnutls_asn2err (result); | ||
822 | } | ||
823 | |||
824 | asn1_write_value (ext, "authorityCertIssuer", NULL, 0); | ||
825 | asn1_write_value (ext, "authorityCertSerialNumber", NULL, 0); | ||
826 | |||
827 | result = _gnutls_x509_der_encode (ext, "", der_ext, 0); | ||
828 | |||
829 | asn1_delete_structure (&ext); | ||
830 | |||
831 | if (result < 0) | ||
832 | { | ||
833 | gnutls_assert (); | ||
834 | return result; | ||
835 | } | ||
836 | |||
837 | return 0; | ||
838 | } | ||
839 | |||
840 | |||
841 | /* Creates and encodes the CRL Distribution points. data_string should be a name | ||
842 | * and type holds the type of the name. | ||
843 | * reason_flags should be an or'ed sequence of GNUTLS_CRL_REASON_*. | ||
844 | * | ||
845 | */ | ||
846 | int | ||
847 | _gnutls_x509_ext_gen_crl_dist_points (gnutls_x509_subject_alt_name_t | ||
848 | type, const void *data_string, | ||
849 | unsigned int reason_flags, | ||
850 | gnutls_datum_t * der_ext) | ||
851 | { | ||
852 | ASN1_TYPE ext = ASN1_TYPE_EMPTY; | ||
853 | gnutls_datum_t gnames = { NULL, 0 }; | ||
854 | int result; | ||
855 | uint8_t reasons[2]; | ||
856 | |||
857 | reasons[0] = reason_flags & 0xff; | ||
858 | reasons[1] = reason_flags >> 8; | ||
859 | |||
860 | result = | ||
861 | asn1_create_element (_gnutls_get_pkix (), | ||
862 | "PKIX1.CRLDistributionPoints", &ext); | ||
863 | if (result != ASN1_SUCCESS) | ||
864 | { | ||
865 | gnutls_assert (); | ||
866 | result = _gnutls_asn2err (result); | ||
867 | goto cleanup; | ||
868 | } | ||
869 | |||
870 | result = asn1_write_value (ext, "", "NEW", 1); | ||
871 | if (result != ASN1_SUCCESS) | ||
872 | { | ||
873 | gnutls_assert (); | ||
874 | result = _gnutls_asn2err (result); | ||
875 | goto cleanup; | ||
876 | } | ||
877 | |||
878 | if (reason_flags) | ||
879 | { | ||
880 | result = asn1_write_value (ext, "?LAST.reasons", reasons, 9); | ||
881 | if (result != ASN1_SUCCESS) | ||
882 | { | ||
883 | gnutls_assert (); | ||
884 | result = _gnutls_asn2err (result); | ||
885 | goto cleanup; | ||
886 | } | ||
887 | } | ||
888 | else | ||
889 | { | ||
890 | result = asn1_write_value (ext, "?LAST.reasons", NULL, 0); | ||
891 | if (result != ASN1_SUCCESS) | ||
892 | { | ||
893 | gnutls_assert (); | ||
894 | result = _gnutls_asn2err (result); | ||
895 | goto cleanup; | ||
896 | } | ||
897 | } | ||
898 | |||
899 | result = asn1_write_value (ext, "?LAST.cRLIssuer", NULL, 0); | ||
900 | if (result != ASN1_SUCCESS) | ||
901 | { | ||
902 | gnutls_assert (); | ||
903 | result = _gnutls_asn2err (result); | ||
904 | goto cleanup; | ||
905 | } | ||
906 | |||
907 | /* When used as type CHOICE. | ||
908 | */ | ||
909 | result = asn1_write_value (ext, "?LAST.distributionPoint", "fullName", 1); | ||
910 | if (result != ASN1_SUCCESS) | ||
911 | { | ||
912 | gnutls_assert (); | ||
913 | result = _gnutls_asn2err (result); | ||
914 | goto cleanup; | ||
915 | } | ||
916 | |||
917 | #if 0 | ||
918 | /* only needed in old code (where defined as SEQUENCE OF) */ | ||
919 | asn1_write_value (ext, | ||
920 | "?LAST.distributionPoint.nameRelativeToCRLIssuer", | ||
921 | NULL, 0); | ||
922 | #endif | ||
923 | |||
924 | result = | ||
925 | write_new_general_name (ext, "?LAST.distributionPoint.fullName", | ||
926 | type, data_string); | ||
927 | if (result < 0) | ||
928 | { | ||
929 | gnutls_assert (); | ||
930 | goto cleanup; | ||
931 | } | ||
932 | |||
933 | result = _gnutls_x509_der_encode (ext, "", der_ext, 0); | ||
934 | |||
935 | if (result < 0) | ||
936 | { | ||
937 | gnutls_assert (); | ||
938 | goto cleanup; | ||
939 | } | ||
940 | |||
941 | result = 0; | ||
942 | |||
943 | cleanup: | ||
944 | _gnutls_free_datum (&gnames); | ||
945 | asn1_delete_structure (&ext); | ||
946 | |||
947 | return result; | ||
948 | } | ||
949 | |||
950 | /* extract the proxyCertInfo from the DER encoded extension | ||
951 | */ | ||
952 | int | ||
953 | _gnutls_x509_ext_extract_proxyCertInfo (int *pathLenConstraint, | ||
954 | char **policyLanguage, | ||
955 | char **policy, | ||
956 | size_t * sizeof_policy, | ||
957 | opaque * extnValue, int extnValueLen) | ||
958 | { | ||
959 | ASN1_TYPE ext = ASN1_TYPE_EMPTY; | ||
960 | int result; | ||
961 | gnutls_datum_t value; | ||
962 | |||
963 | if ((result = asn1_create_element | ||
964 | (_gnutls_get_pkix (), "PKIX1.ProxyCertInfo", &ext)) != ASN1_SUCCESS) | ||
965 | { | ||
966 | gnutls_assert (); | ||
967 | return _gnutls_asn2err (result); | ||
968 | } | ||
969 | |||
970 | result = asn1_der_decoding (&ext, extnValue, extnValueLen, NULL); | ||
971 | if (result != ASN1_SUCCESS) | ||
972 | { | ||
973 | gnutls_assert (); | ||
974 | asn1_delete_structure (&ext); | ||
975 | return _gnutls_asn2err (result); | ||
976 | } | ||
977 | |||
978 | if (pathLenConstraint) | ||
979 | { | ||
980 | result = _gnutls_x509_read_uint (ext, "pCPathLenConstraint", | ||
981 | pathLenConstraint); | ||
982 | if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) | ||
983 | *pathLenConstraint = -1; | ||
984 | else if (result != GNUTLS_E_SUCCESS) | ||
985 | { | ||
986 | asn1_delete_structure (&ext); | ||
987 | return _gnutls_asn2err (result); | ||
988 | } | ||
989 | } | ||
990 | |||
991 | result = _gnutls_x509_read_value (ext, "proxyPolicy.policyLanguage", | ||
992 | &value, 0); | ||
993 | if (result < 0) | ||
994 | { | ||
995 | gnutls_assert (); | ||
996 | asn1_delete_structure (&ext); | ||
997 | return result; | ||
998 | } | ||
999 | |||
1000 | if (policyLanguage) | ||
1001 | *policyLanguage = gnutls_strdup (value.data); | ||
1002 | |||
1003 | result = _gnutls_x509_read_value (ext, "proxyPolicy.policy", &value, 0); | ||
1004 | if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) | ||
1005 | { | ||
1006 | if (policy) | ||
1007 | *policy = NULL; | ||
1008 | if (sizeof_policy) | ||
1009 | *sizeof_policy = 0; | ||
1010 | } | ||
1011 | else if (result < 0) | ||
1012 | { | ||
1013 | gnutls_assert (); | ||
1014 | asn1_delete_structure (&ext); | ||
1015 | return result; | ||
1016 | } | ||
1017 | else | ||
1018 | { | ||
1019 | if (policy) | ||
1020 | *policy = value.data; | ||
1021 | if (sizeof_policy) | ||
1022 | *sizeof_policy = value.size; | ||
1023 | } | ||
1024 | |||
1025 | asn1_delete_structure (&ext); | ||
1026 | |||
1027 | return 0; | ||
1028 | } | ||
1029 | |||
1030 | /* generate the proxyCertInfo in a DER encoded extension | ||
1031 | */ | ||
1032 | int | ||
1033 | _gnutls_x509_ext_gen_proxyCertInfo (int pathLenConstraint, | ||
1034 | const char *policyLanguage, | ||
1035 | const char *policy, | ||
1036 | size_t sizeof_policy, | ||
1037 | gnutls_datum_t * der_ext) | ||
1038 | { | ||
1039 | ASN1_TYPE ext = ASN1_TYPE_EMPTY; | ||
1040 | int result; | ||
1041 | |||
1042 | result = asn1_create_element (_gnutls_get_pkix (), | ||
1043 | "PKIX1.ProxyCertInfo", &ext); | ||
1044 | if (result != ASN1_SUCCESS) | ||
1045 | { | ||
1046 | gnutls_assert (); | ||
1047 | return _gnutls_asn2err (result); | ||
1048 | } | ||
1049 | |||
1050 | if (pathLenConstraint < 0) | ||
1051 | { | ||
1052 | result = asn1_write_value (ext, "pCPathLenConstraint", NULL, 0); | ||
1053 | if (result < 0) | ||
1054 | result = _gnutls_asn2err (result); | ||
1055 | } | ||
1056 | else | ||
1057 | result = _gnutls_x509_write_uint32 (ext, "pCPathLenConstraint", | ||
1058 | pathLenConstraint); | ||
1059 | if (result < 0) | ||
1060 | { | ||
1061 | gnutls_assert (); | ||
1062 | asn1_delete_structure (&ext); | ||
1063 | return result; | ||
1064 | } | ||
1065 | |||
1066 | result = asn1_write_value (ext, "proxyPolicy.policyLanguage", | ||
1067 | policyLanguage, 1); | ||
1068 | if (result < 0) | ||
1069 | { | ||
1070 | gnutls_assert (); | ||
1071 | asn1_delete_structure (&ext); | ||
1072 | return _gnutls_asn2err (result); | ||
1073 | } | ||
1074 | |||
1075 | result = asn1_write_value (ext, "proxyPolicy.policy", | ||
1076 | policy, sizeof_policy); | ||
1077 | if (result < 0) | ||
1078 | { | ||
1079 | gnutls_assert (); | ||
1080 | asn1_delete_structure (&ext); | ||
1081 | return _gnutls_asn2err (result); | ||
1082 | } | ||
1083 | |||
1084 | result = _gnutls_x509_der_encode (ext, "", der_ext, 0); | ||
1085 | |||
1086 | asn1_delete_structure (&ext); | ||
1087 | |||
1088 | if (result < 0) | ||
1089 | { | ||
1090 | gnutls_assert (); | ||
1091 | return result; | ||
1092 | } | ||
1093 | |||
1094 | return 0; | ||
1095 | } | ||
diff --git a/src/daemon/https/x509/extensions.h b/src/daemon/https/x509/extensions.h new file mode 100644 index 00000000..fb758c90 --- /dev/null +++ b/src/daemon/https/x509/extensions.h | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | int _gnutls_x509_crt_get_extension (gnutls_x509_crt_t cert, | ||
26 | const char *extension_id, int indx, | ||
27 | gnutls_datum_t * ret, | ||
28 | unsigned int *critical); | ||
29 | |||
30 | int _gnutls_x509_crt_get_extension_oid (gnutls_x509_crt_t cert, | ||
31 | int indx, void *ret, | ||
32 | size_t * ret_size); | ||
33 | int _gnutls_x509_ext_extract_keyUsage (uint16_t * keyUsage, | ||
34 | opaque * extnValue, int extnValueLen); | ||
35 | int _gnutls_x509_ext_extract_basicConstraints (int *CA, | ||
36 | int *pathLenConstraint, | ||
37 | opaque * extnValue, | ||
38 | int extnValueLen); | ||
39 | int _gnutls_x509_crt_set_extension (gnutls_x509_crt_t cert, | ||
40 | const char *extension_id, | ||
41 | const gnutls_datum_t * ext_data, | ||
42 | unsigned int critical); | ||
43 | int _gnutls_x509_ext_gen_basicConstraints (int CA, int pathLenConstraint, | ||
44 | gnutls_datum_t * der_ext); | ||
45 | int _gnutls_x509_ext_gen_keyUsage (uint16_t usage, gnutls_datum_t * der_ext); | ||
46 | int _gnutls_x509_ext_gen_subject_alt_name (gnutls_x509_subject_alt_name_t | ||
47 | type, const char *data_string, | ||
48 | gnutls_datum_t * der_ext); | ||
49 | int _gnutls_x509_ext_gen_crl_dist_points (gnutls_x509_subject_alt_name_t | ||
50 | type, const void *data_string, | ||
51 | unsigned int reason_flags, | ||
52 | gnutls_datum_t * der_ext); | ||
53 | int _gnutls_x509_ext_gen_key_id (const void *id, size_t id_size, | ||
54 | gnutls_datum_t * der_data); | ||
55 | int _gnutls_x509_ext_gen_auth_key_id (const void *id, size_t id_size, | ||
56 | gnutls_datum_t * der_data); | ||
57 | |||
58 | int _gnutls_x509_ext_extract_proxyCertInfo (int *pathLenConstraint, | ||
59 | char **policyLanguage, | ||
60 | char **policy, | ||
61 | size_t *sizeof_policy, | ||
62 | opaque * extnValue, | ||
63 | int extnValueLen); | ||
64 | int _gnutls_x509_ext_gen_proxyCertInfo (int pathLenConstraint, | ||
65 | const char *policyLanguage, | ||
66 | const char *policy, | ||
67 | size_t sizeof_policy, | ||
68 | gnutls_datum_t * der_ext); | ||
diff --git a/src/daemon/https/x509/mpi.c b/src/daemon/https/x509/mpi.c new file mode 100644 index 00000000..8cc43855 --- /dev/null +++ b/src/daemon/https/x509/mpi.c | |||
@@ -0,0 +1,576 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <gnutls_int.h> | ||
26 | #include <gnutls_errors.h> | ||
27 | #include <gnutls_global.h> | ||
28 | #include <libtasn1.h> | ||
29 | #include <gnutls_datum.h> | ||
30 | #include "common.h" | ||
31 | #include "x509.h" | ||
32 | #include <gnutls_num.h> | ||
33 | #include "mpi.h" | ||
34 | |||
35 | /* | ||
36 | * some x509 certificate parsing functions that relate to MPI parameter | ||
37 | * extraction. This reads the BIT STRING subjectPublicKey. | ||
38 | * Returns 2 parameters (m,e). | ||
39 | */ | ||
40 | int | ||
41 | _gnutls_x509_read_rsa_params (opaque * der, int dersize, mpi_t * params) | ||
42 | { | ||
43 | int result; | ||
44 | ASN1_TYPE spk = ASN1_TYPE_EMPTY; | ||
45 | |||
46 | if ((result = | ||
47 | asn1_create_element (_gnutls_get_gnutls_asn (), "GNUTLS.RSAPublicKey", | ||
48 | &spk)) != ASN1_SUCCESS) | ||
49 | { | ||
50 | gnutls_assert (); | ||
51 | return _gnutls_asn2err (result); | ||
52 | } | ||
53 | |||
54 | result = asn1_der_decoding (&spk, der, dersize, NULL); | ||
55 | |||
56 | if (result != ASN1_SUCCESS) | ||
57 | { | ||
58 | gnutls_assert (); | ||
59 | asn1_delete_structure (&spk); | ||
60 | return _gnutls_asn2err (result); | ||
61 | } | ||
62 | |||
63 | if ((result = _gnutls_x509_read_int (spk, "modulus", ¶ms[0])) < 0) | ||
64 | { | ||
65 | gnutls_assert (); | ||
66 | asn1_delete_structure (&spk); | ||
67 | return GNUTLS_E_ASN1_GENERIC_ERROR; | ||
68 | } | ||
69 | |||
70 | if ((result = | ||
71 | _gnutls_x509_read_int (spk, "publicExponent", ¶ms[1])) < 0) | ||
72 | { | ||
73 | gnutls_assert (); | ||
74 | _gnutls_mpi_release (¶ms[0]); | ||
75 | asn1_delete_structure (&spk); | ||
76 | return GNUTLS_E_ASN1_GENERIC_ERROR; | ||
77 | } | ||
78 | |||
79 | asn1_delete_structure (&spk); | ||
80 | |||
81 | return 0; | ||
82 | |||
83 | } | ||
84 | |||
85 | /* reads p,q and g | ||
86 | * from the certificate (subjectPublicKey BIT STRING). | ||
87 | * params[0-2] | ||
88 | */ | ||
89 | int | ||
90 | _gnutls_x509_read_dsa_params (opaque * der, int dersize, mpi_t * params) | ||
91 | { | ||
92 | int result; | ||
93 | ASN1_TYPE spk = ASN1_TYPE_EMPTY; | ||
94 | |||
95 | if ((result = | ||
96 | asn1_create_element (_gnutls_get_pkix (), "PKIX1.Dss-Parms", | ||
97 | &spk)) != ASN1_SUCCESS) | ||
98 | { | ||
99 | gnutls_assert (); | ||
100 | return _gnutls_asn2err (result); | ||
101 | } | ||
102 | |||
103 | result = asn1_der_decoding (&spk, der, dersize, NULL); | ||
104 | |||
105 | if (result != ASN1_SUCCESS) | ||
106 | { | ||
107 | gnutls_assert (); | ||
108 | asn1_delete_structure (&spk); | ||
109 | return _gnutls_asn2err (result); | ||
110 | } | ||
111 | |||
112 | /* FIXME: If the parameters are not included in the certificate | ||
113 | * then the issuer's parameters should be used. This is not | ||
114 | * done yet. | ||
115 | */ | ||
116 | |||
117 | /* Read p */ | ||
118 | |||
119 | if ((result = _gnutls_x509_read_int (spk, "p", ¶ms[0])) < 0) | ||
120 | { | ||
121 | gnutls_assert (); | ||
122 | asn1_delete_structure (&spk); | ||
123 | return GNUTLS_E_ASN1_GENERIC_ERROR; | ||
124 | } | ||
125 | |||
126 | /* Read q */ | ||
127 | |||
128 | if ((result = _gnutls_x509_read_int (spk, "q", ¶ms[1])) < 0) | ||
129 | { | ||
130 | gnutls_assert (); | ||
131 | asn1_delete_structure (&spk); | ||
132 | _gnutls_mpi_release (¶ms[0]); | ||
133 | return GNUTLS_E_ASN1_GENERIC_ERROR; | ||
134 | } | ||
135 | |||
136 | /* Read g */ | ||
137 | |||
138 | if ((result = _gnutls_x509_read_int (spk, "g", ¶ms[2])) < 0) | ||
139 | { | ||
140 | gnutls_assert (); | ||
141 | asn1_delete_structure (&spk); | ||
142 | _gnutls_mpi_release (¶ms[0]); | ||
143 | _gnutls_mpi_release (¶ms[1]); | ||
144 | return GNUTLS_E_ASN1_GENERIC_ERROR; | ||
145 | } | ||
146 | |||
147 | asn1_delete_structure (&spk); | ||
148 | |||
149 | return 0; | ||
150 | |||
151 | } | ||
152 | |||
153 | /* Reads an Integer from the DER encoded data | ||
154 | */ | ||
155 | |||
156 | int | ||
157 | _gnutls_x509_read_der_int (opaque * der, int dersize, mpi_t * out) | ||
158 | { | ||
159 | int result; | ||
160 | ASN1_TYPE spk = ASN1_TYPE_EMPTY; | ||
161 | |||
162 | /* == INTEGER */ | ||
163 | if ((result = | ||
164 | asn1_create_element (_gnutls_get_gnutls_asn (), "GNUTLS.DSAPublicKey", | ||
165 | &spk)) != ASN1_SUCCESS) | ||
166 | { | ||
167 | gnutls_assert (); | ||
168 | return _gnutls_asn2err (result); | ||
169 | } | ||
170 | |||
171 | result = asn1_der_decoding (&spk, der, dersize, NULL); | ||
172 | |||
173 | if (result != ASN1_SUCCESS) | ||
174 | { | ||
175 | gnutls_assert (); | ||
176 | asn1_delete_structure (&spk); | ||
177 | return _gnutls_asn2err (result); | ||
178 | } | ||
179 | |||
180 | /* Read Y */ | ||
181 | |||
182 | if ((result = _gnutls_x509_read_int (spk, "", out)) < 0) | ||
183 | { | ||
184 | gnutls_assert (); | ||
185 | asn1_delete_structure (&spk); | ||
186 | return _gnutls_asn2err (result); | ||
187 | } | ||
188 | |||
189 | asn1_delete_structure (&spk); | ||
190 | |||
191 | return 0; | ||
192 | |||
193 | } | ||
194 | |||
195 | /* reads DSA's Y | ||
196 | * from the certificate | ||
197 | * only sets params[3] | ||
198 | */ | ||
199 | int | ||
200 | _gnutls_x509_read_dsa_pubkey (opaque * der, int dersize, mpi_t * params) | ||
201 | { | ||
202 | return _gnutls_x509_read_der_int (der, dersize, ¶ms[3]); | ||
203 | } | ||
204 | |||
205 | /* Extracts DSA and RSA parameters from a certificate. | ||
206 | */ | ||
207 | int | ||
208 | _gnutls_x509_crt_get_mpis (gnutls_x509_crt_t cert, | ||
209 | mpi_t * params, int *params_size) | ||
210 | { | ||
211 | int result; | ||
212 | int pk_algorithm; | ||
213 | gnutls_datum tmp = { NULL, 0 }; | ||
214 | |||
215 | /* Read the algorithm's OID | ||
216 | */ | ||
217 | pk_algorithm = gnutls_x509_crt_get_pk_algorithm (cert, NULL); | ||
218 | |||
219 | /* Read the algorithm's parameters | ||
220 | */ | ||
221 | result | ||
222 | = _gnutls_x509_read_value (cert->cert, | ||
223 | "tbsCertificate.subjectPublicKeyInfo.subjectPublicKey", | ||
224 | &tmp, 2); | ||
225 | |||
226 | if (result < 0) | ||
227 | { | ||
228 | gnutls_assert (); | ||
229 | return result; | ||
230 | } | ||
231 | |||
232 | switch (pk_algorithm) | ||
233 | { | ||
234 | case GNUTLS_PK_RSA: | ||
235 | /* params[0] is the modulus, | ||
236 | * params[1] is the exponent | ||
237 | */ | ||
238 | if (*params_size < RSA_PUBLIC_PARAMS) | ||
239 | { | ||
240 | gnutls_assert (); | ||
241 | /* internal error. Increase the mpi_ts in params */ | ||
242 | result = GNUTLS_E_INTERNAL_ERROR; | ||
243 | goto error; | ||
244 | } | ||
245 | |||
246 | if ((result = | ||
247 | _gnutls_x509_read_rsa_params (tmp.data, tmp.size, params)) < 0) | ||
248 | { | ||
249 | gnutls_assert (); | ||
250 | goto error; | ||
251 | } | ||
252 | *params_size = RSA_PUBLIC_PARAMS; | ||
253 | |||
254 | break; | ||
255 | default: | ||
256 | /* other types like DH | ||
257 | * currently not supported | ||
258 | */ | ||
259 | gnutls_assert (); | ||
260 | result = GNUTLS_E_X509_CERTIFICATE_ERROR; | ||
261 | goto error; | ||
262 | } | ||
263 | |||
264 | result = 0; | ||
265 | |||
266 | error:_gnutls_free_datum (&tmp); | ||
267 | return result; | ||
268 | } | ||
269 | |||
270 | /* | ||
271 | * some x509 certificate functions that relate to MPI parameter | ||
272 | * setting. This writes the BIT STRING subjectPublicKey. | ||
273 | * Needs 2 parameters (m,e). | ||
274 | * | ||
275 | * Allocates the space used to store the DER data. | ||
276 | */ | ||
277 | int | ||
278 | _gnutls_x509_write_rsa_params (mpi_t * params, | ||
279 | int params_size, gnutls_datum_t * der) | ||
280 | { | ||
281 | int result; | ||
282 | ASN1_TYPE spk = ASN1_TYPE_EMPTY; | ||
283 | |||
284 | der->data = NULL; | ||
285 | der->size = 0; | ||
286 | |||
287 | if (params_size < 2) | ||
288 | { | ||
289 | gnutls_assert (); | ||
290 | result = GNUTLS_E_INVALID_REQUEST; | ||
291 | goto cleanup; | ||
292 | } | ||
293 | |||
294 | if ((result = | ||
295 | asn1_create_element (_gnutls_get_gnutls_asn (), "GNUTLS.RSAPublicKey", | ||
296 | &spk)) != ASN1_SUCCESS) | ||
297 | { | ||
298 | gnutls_assert (); | ||
299 | return _gnutls_asn2err (result); | ||
300 | } | ||
301 | |||
302 | result = _gnutls_x509_write_int (spk, "modulus", params[0], 0); | ||
303 | if (result < 0) | ||
304 | { | ||
305 | gnutls_assert (); | ||
306 | goto cleanup; | ||
307 | } | ||
308 | |||
309 | result = _gnutls_x509_write_int (spk, "publicExponent", params[1], 0); | ||
310 | if (result < 0) | ||
311 | { | ||
312 | gnutls_assert (); | ||
313 | goto cleanup; | ||
314 | } | ||
315 | |||
316 | result = _gnutls_x509_der_encode (spk, "", der, 0); | ||
317 | if (result < 0) | ||
318 | { | ||
319 | gnutls_assert (); | ||
320 | goto cleanup; | ||
321 | } | ||
322 | |||
323 | asn1_delete_structure (&spk); | ||
324 | return 0; | ||
325 | |||
326 | cleanup:asn1_delete_structure (&spk); | ||
327 | |||
328 | return result; | ||
329 | } | ||
330 | |||
331 | /* | ||
332 | * This function writes and encodes the parameters for DSS or RSA keys. | ||
333 | * This is the "signatureAlgorithm" fields. | ||
334 | */ | ||
335 | int | ||
336 | _gnutls_x509_write_sig_params (ASN1_TYPE dst, | ||
337 | const char *dst_name, | ||
338 | gnutls_pk_algorithm_t pk_algorithm, | ||
339 | gnutls_digest_algorithm_t dig, | ||
340 | mpi_t * params, int params_size) | ||
341 | { | ||
342 | gnutls_datum_t der; | ||
343 | int result; | ||
344 | char name[128]; | ||
345 | const char *pk; | ||
346 | |||
347 | _gnutls_str_cpy (name, sizeof (name), dst_name); | ||
348 | _gnutls_str_cat (name, sizeof (name), ".algorithm"); | ||
349 | |||
350 | pk = _gnutls_x509_sign_to_oid (pk_algorithm, HASH2MAC (dig)); | ||
351 | if (pk == NULL) | ||
352 | { | ||
353 | gnutls_assert (); | ||
354 | return GNUTLS_E_INVALID_REQUEST; | ||
355 | } | ||
356 | |||
357 | /* write the OID. | ||
358 | */ | ||
359 | result = asn1_write_value (dst, name, pk, 1); | ||
360 | if (result != ASN1_SUCCESS) | ||
361 | { | ||
362 | gnutls_assert (); | ||
363 | return _gnutls_asn2err (result); | ||
364 | } | ||
365 | |||
366 | _gnutls_str_cpy (name, sizeof (name), dst_name); | ||
367 | _gnutls_str_cat (name, sizeof (name), ".parameters"); | ||
368 | |||
369 | if (pk_algorithm == GNUTLS_PK_RSA) | ||
370 | { /* RSA */ | ||
371 | result = asn1_write_value (dst, name, NULL, 0); | ||
372 | |||
373 | if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND) | ||
374 | { | ||
375 | /* Here we ignore the element not found error, since this | ||
376 | * may have been disabled before. | ||
377 | */ | ||
378 | gnutls_assert (); | ||
379 | return _gnutls_asn2err (result); | ||
380 | } | ||
381 | } | ||
382 | |||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | /* | ||
387 | * This function writes the parameters for DSS keys. | ||
388 | * Needs 3 parameters (p,q,g). | ||
389 | * | ||
390 | * Allocates the space used to store the DER data. | ||
391 | */ | ||
392 | int | ||
393 | _gnutls_x509_write_dsa_params (mpi_t * params, | ||
394 | int params_size, gnutls_datum_t * der) | ||
395 | { | ||
396 | int result; | ||
397 | ASN1_TYPE spk = ASN1_TYPE_EMPTY; | ||
398 | |||
399 | der->data = NULL; | ||
400 | der->size = 0; | ||
401 | |||
402 | if (params_size < 3) | ||
403 | { | ||
404 | gnutls_assert (); | ||
405 | result = GNUTLS_E_INVALID_REQUEST; | ||
406 | goto cleanup; | ||
407 | } | ||
408 | |||
409 | if ((result = | ||
410 | asn1_create_element (_gnutls_get_gnutls_asn (), "GNUTLS.DSAParameters", | ||
411 | &spk)) != ASN1_SUCCESS) | ||
412 | { | ||
413 | gnutls_assert (); | ||
414 | return _gnutls_asn2err (result); | ||
415 | } | ||
416 | |||
417 | result = _gnutls_x509_write_int (spk, "p", params[0], 0); | ||
418 | if (result < 0) | ||
419 | { | ||
420 | gnutls_assert (); | ||
421 | goto cleanup; | ||
422 | } | ||
423 | |||
424 | result = _gnutls_x509_write_int (spk, "q", params[1], 0); | ||
425 | if (result < 0) | ||
426 | { | ||
427 | gnutls_assert (); | ||
428 | goto cleanup; | ||
429 | } | ||
430 | |||
431 | result = _gnutls_x509_write_int (spk, "g", params[2], 0); | ||
432 | if (result < 0) | ||
433 | { | ||
434 | gnutls_assert (); | ||
435 | goto cleanup; | ||
436 | } | ||
437 | |||
438 | result = _gnutls_x509_der_encode (spk, "", der, 0); | ||
439 | if (result < 0) | ||
440 | { | ||
441 | gnutls_assert (); | ||
442 | goto cleanup; | ||
443 | } | ||
444 | |||
445 | result = 0; | ||
446 | |||
447 | cleanup:asn1_delete_structure (&spk); | ||
448 | return result; | ||
449 | } | ||
450 | |||
451 | /* | ||
452 | * This function writes the public parameters for DSS keys. | ||
453 | * Needs 1 parameter (y). | ||
454 | * | ||
455 | * Allocates the space used to store the DER data. | ||
456 | */ | ||
457 | int | ||
458 | _gnutls_x509_write_dsa_public_key (mpi_t * params, | ||
459 | int params_size, gnutls_datum_t * der) | ||
460 | { | ||
461 | int result; | ||
462 | ASN1_TYPE spk = ASN1_TYPE_EMPTY; | ||
463 | |||
464 | der->data = NULL; | ||
465 | der->size = 0; | ||
466 | |||
467 | if (params_size < 3) | ||
468 | { | ||
469 | gnutls_assert (); | ||
470 | result = GNUTLS_E_INVALID_REQUEST; | ||
471 | goto cleanup; | ||
472 | } | ||
473 | |||
474 | if ((result = | ||
475 | asn1_create_element (_gnutls_get_gnutls_asn (), "GNUTLS.DSAPublicKey", | ||
476 | &spk)) != ASN1_SUCCESS) | ||
477 | { | ||
478 | gnutls_assert (); | ||
479 | return _gnutls_asn2err (result); | ||
480 | } | ||
481 | |||
482 | result = _gnutls_x509_write_int (spk, "", params[3], 0); | ||
483 | if (result < 0) | ||
484 | { | ||
485 | gnutls_assert (); | ||
486 | goto cleanup; | ||
487 | } | ||
488 | |||
489 | result = _gnutls_x509_der_encode (spk, "", der, 0); | ||
490 | if (result < 0) | ||
491 | { | ||
492 | gnutls_assert (); | ||
493 | goto cleanup; | ||
494 | } | ||
495 | |||
496 | asn1_delete_structure (&spk); | ||
497 | return 0; | ||
498 | |||
499 | cleanup:asn1_delete_structure (&spk); | ||
500 | return result; | ||
501 | } | ||
502 | |||
503 | /* this function reads a (small) unsigned integer | ||
504 | * from asn1 structs. Combines the read and the convertion | ||
505 | * steps. | ||
506 | */ | ||
507 | int | ||
508 | _gnutls_x509_read_uint (ASN1_TYPE node, const char *value, unsigned int *ret) | ||
509 | { | ||
510 | int len, result; | ||
511 | opaque *tmpstr; | ||
512 | |||
513 | len = 0; | ||
514 | result = asn1_read_value (node, value, NULL, &len); | ||
515 | if (result != ASN1_MEM_ERROR) | ||
516 | { | ||
517 | gnutls_assert (); | ||
518 | return _gnutls_asn2err (result); | ||
519 | } | ||
520 | |||
521 | tmpstr = gnutls_alloca (len); | ||
522 | if (tmpstr == NULL) | ||
523 | { | ||
524 | gnutls_assert (); | ||
525 | return GNUTLS_E_MEMORY_ERROR; | ||
526 | } | ||
527 | |||
528 | result = asn1_read_value (node, value, tmpstr, &len); | ||
529 | |||
530 | if (result != ASN1_SUCCESS) | ||
531 | { | ||
532 | gnutls_assert (); | ||
533 | gnutls_afree (tmpstr); | ||
534 | return _gnutls_asn2err (result); | ||
535 | } | ||
536 | |||
537 | if (len == 1) | ||
538 | *ret = tmpstr[0]; | ||
539 | else if (len == 2) | ||
540 | *ret = _gnutls_read_uint16 (tmpstr); | ||
541 | else if (len == 3) | ||
542 | *ret = _gnutls_read_uint24 (tmpstr); | ||
543 | else if (len == 4) | ||
544 | *ret = _gnutls_read_uint32 (tmpstr); | ||
545 | else | ||
546 | { | ||
547 | gnutls_assert (); | ||
548 | gnutls_afree (tmpstr); | ||
549 | return GNUTLS_E_INTERNAL_ERROR; | ||
550 | } | ||
551 | |||
552 | gnutls_afree (tmpstr); | ||
553 | |||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | /* Writes the specified integer into the specified node. | ||
558 | */ | ||
559 | int | ||
560 | _gnutls_x509_write_uint32 (ASN1_TYPE node, const char *value, uint32_t num) | ||
561 | { | ||
562 | opaque tmpstr[4]; | ||
563 | int result; | ||
564 | |||
565 | _gnutls_write_uint32 (num, tmpstr); | ||
566 | |||
567 | result = asn1_write_value (node, value, tmpstr, 4); | ||
568 | |||
569 | if (result != ASN1_SUCCESS) | ||
570 | { | ||
571 | gnutls_assert (); | ||
572 | return _gnutls_asn2err (result); | ||
573 | } | ||
574 | |||
575 | return 0; | ||
576 | } | ||
diff --git a/src/daemon/https/x509/mpi.h b/src/daemon/https/x509/mpi.h new file mode 100644 index 00000000..785d7e02 --- /dev/null +++ b/src/daemon/https/x509/mpi.h | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <gnutls_int.h> | ||
26 | #include "x509.h" | ||
27 | |||
28 | int _gnutls_x509_crt_get_mpis (gnutls_x509_crt_t cert, | ||
29 | mpi_t * params, int *params_size); | ||
30 | int _gnutls_x509_read_rsa_params (opaque * der, int dersize, mpi_t * params); | ||
31 | int _gnutls_x509_read_dsa_pubkey (opaque * der, int dersize, mpi_t * params); | ||
32 | int _gnutls_x509_read_dsa_params (opaque * der, int dersize, mpi_t * params); | ||
33 | |||
34 | int _gnutls_x509_write_rsa_params (mpi_t * params, int params_size, | ||
35 | gnutls_datum_t * der); | ||
36 | int _gnutls_x509_write_dsa_params (mpi_t * params, int params_size, | ||
37 | gnutls_datum_t * der); | ||
38 | int _gnutls_x509_write_dsa_public_key (mpi_t * params, int params_size, | ||
39 | gnutls_datum_t * der); | ||
40 | |||
41 | int _gnutls_x509_read_uint (ASN1_TYPE node, const char *value, | ||
42 | unsigned int *ret); | ||
43 | |||
44 | int | ||
45 | _gnutls_x509_read_der_int (opaque * der, int dersize, mpi_t* out); | ||
46 | |||
47 | int _gnutls_x509_read_int (ASN1_TYPE node, const char *value, | ||
48 | mpi_t * ret_mpi); | ||
49 | int _gnutls_x509_write_int (ASN1_TYPE node, const char *value, mpi_t mpi, | ||
50 | int lz); | ||
51 | int _gnutls_x509_write_uint32 (ASN1_TYPE node, const char *value, | ||
52 | uint32_t num); | ||
53 | |||
54 | int _gnutls_x509_write_sig_params (ASN1_TYPE dst, const char *dst_name, | ||
55 | gnutls_pk_algorithm_t pk_algorithm, | ||
56 | gnutls_digest_algorithm_t, mpi_t * params, | ||
57 | int params_size); | ||
diff --git a/src/daemon/https/x509/output.c b/src/daemon/https/x509/output.c new file mode 100644 index 00000000..dcc87ab1 --- /dev/null +++ b/src/daemon/https/x509/output.c | |||
@@ -0,0 +1,1360 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Free Software Foundation | ||
3 | * | ||
4 | * Author: Simon Josefsson | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
21 | * 02110-1301, USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | /* Functions for printing X.509 Certificate structures | ||
26 | */ | ||
27 | |||
28 | #include <gnutls_int.h> | ||
29 | #include <common.h> | ||
30 | #include <gnutls_x509.h> | ||
31 | #include <x509.h> | ||
32 | #include <gnutls_errors.h> | ||
33 | |||
34 | /* I18n of error codes. */ | ||
35 | #include "gettext.h" | ||
36 | #define _(String) dgettext (PACKAGE, String) | ||
37 | #define N_(String) gettext_noop (String) | ||
38 | |||
39 | #define addf _gnutls_string_append_printf | ||
40 | #define adds _gnutls_string_append_str | ||
41 | |||
42 | static void | ||
43 | hexdump (gnutls_string * str, const char *data, size_t len, const char *spc) | ||
44 | { | ||
45 | size_t j; | ||
46 | |||
47 | if (spc) | ||
48 | adds (str, spc); | ||
49 | for (j = 0; j < len; j++) | ||
50 | { | ||
51 | if (((j + 1) % 16) == 0) | ||
52 | { | ||
53 | addf (str, "%.2x\n", (unsigned char) data[j]); | ||
54 | if (spc && j != (len - 1)) | ||
55 | adds (str, spc); | ||
56 | } | ||
57 | else if (j == (len - 1)) | ||
58 | addf (str, "%.2x", (unsigned char) data[j]); | ||
59 | else | ||
60 | addf (str, "%.2x:", (unsigned char) data[j]); | ||
61 | } | ||
62 | if ((j % 16) != 0) | ||
63 | adds (str, "\n"); | ||
64 | } | ||
65 | |||
66 | static void | ||
67 | hexprint (gnutls_string * str, const char *data, size_t len) | ||
68 | { | ||
69 | size_t j; | ||
70 | |||
71 | if (len == 0) | ||
72 | adds (str, "00"); | ||
73 | else | ||
74 | { | ||
75 | for (j = 0; j < len; j++) | ||
76 | addf (str, "%.2x", (unsigned char) data[j]); | ||
77 | } | ||
78 | } | ||
79 | |||
80 | |||
81 | static void | ||
82 | asciiprint (gnutls_string * str, const char *data, size_t len) | ||
83 | { | ||
84 | size_t j; | ||
85 | |||
86 | for (j = 0; j < len; j++) | ||
87 | if (isprint (data[j])) | ||
88 | addf (str, "%c", (unsigned char) data[j]); | ||
89 | else | ||
90 | addf (str, "."); | ||
91 | } | ||
92 | |||
93 | static void | ||
94 | print_proxy (gnutls_string * str, gnutls_x509_crt_t cert) | ||
95 | { | ||
96 | int pathlen; | ||
97 | char *policyLanguage; | ||
98 | char *policy; | ||
99 | size_t npolicy; | ||
100 | int err; | ||
101 | |||
102 | err = gnutls_x509_crt_get_proxy (cert, NULL, | ||
103 | &pathlen, &policyLanguage, | ||
104 | &policy, &npolicy); | ||
105 | if (err < 0) | ||
106 | { | ||
107 | addf (str, "error: get_proxy: %s\n", gnutls_strerror (err)); | ||
108 | return; | ||
109 | } | ||
110 | |||
111 | if (pathlen >= 0) | ||
112 | addf (str, _("\t\t\tPath Length Constraint: %d\n"), pathlen); | ||
113 | addf (str, _("\t\t\tPolicy Language: %s"), policyLanguage); | ||
114 | if (strcmp (policyLanguage, "1.3.6.1.5.5.7.21.1") == 0) | ||
115 | adds (str, " (id-ppl-inheritALL)\n"); | ||
116 | else if (strcmp (policyLanguage, "1.3.6.1.5.5.7.21.2") == 0) | ||
117 | adds (str, " (id-ppl-independent)\n"); | ||
118 | else | ||
119 | adds (str, "\n"); | ||
120 | if (npolicy) | ||
121 | { | ||
122 | adds (str, _("\t\t\tPolicy:\n\t\t\t\tASCII: ")); | ||
123 | asciiprint (str, policy, npolicy); | ||
124 | adds (str, _("\n\t\t\t\tHexdump: ")); | ||
125 | hexprint (str, policy, npolicy); | ||
126 | adds (str, "\n"); | ||
127 | } | ||
128 | } | ||
129 | |||
130 | static void | ||
131 | print_ski (gnutls_string * str, gnutls_x509_crt_t cert) | ||
132 | { | ||
133 | char *buffer = NULL; | ||
134 | size_t size = 0; | ||
135 | int err; | ||
136 | |||
137 | err = gnutls_x509_crt_get_subject_key_id (cert, buffer, &size, NULL); | ||
138 | if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) | ||
139 | { | ||
140 | addf (str, "error: get_subject_key_id: %s\n", gnutls_strerror (err)); | ||
141 | return; | ||
142 | } | ||
143 | |||
144 | buffer = gnutls_malloc (size); | ||
145 | if (!buffer) | ||
146 | { | ||
147 | addf (str, "error: malloc: %s\n", gnutls_strerror (err)); | ||
148 | return; | ||
149 | } | ||
150 | |||
151 | err = gnutls_x509_crt_get_subject_key_id (cert, buffer, &size, NULL); | ||
152 | if (err < 0) | ||
153 | { | ||
154 | gnutls_free (buffer); | ||
155 | addf (str, "error: get_subject_key_id2: %s\n", gnutls_strerror (err)); | ||
156 | return; | ||
157 | } | ||
158 | |||
159 | adds (str, "\t\t\t"); | ||
160 | hexprint (str, buffer, size); | ||
161 | adds (str, "\n"); | ||
162 | |||
163 | gnutls_free (buffer); | ||
164 | } | ||
165 | |||
166 | static void | ||
167 | print_aki (gnutls_string * str, gnutls_x509_crt_t cert) | ||
168 | { | ||
169 | char *buffer = NULL; | ||
170 | size_t size = 0; | ||
171 | int err; | ||
172 | |||
173 | err = gnutls_x509_crt_get_authority_key_id (cert, buffer, &size, NULL); | ||
174 | if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) | ||
175 | { | ||
176 | addf (str, "error: get_authority_key_id: %s\n", gnutls_strerror (err)); | ||
177 | return; | ||
178 | } | ||
179 | |||
180 | buffer = gnutls_malloc (size); | ||
181 | if (!buffer) | ||
182 | { | ||
183 | addf (str, "error: malloc: %s\n", gnutls_strerror (err)); | ||
184 | return; | ||
185 | } | ||
186 | |||
187 | err = gnutls_x509_crt_get_authority_key_id (cert, buffer, &size, NULL); | ||
188 | if (err < 0) | ||
189 | { | ||
190 | gnutls_free (buffer); | ||
191 | addf (str, "error: get_authority_key_id2: %s\n", gnutls_strerror (err)); | ||
192 | return; | ||
193 | } | ||
194 | |||
195 | adds (str, "\t\t\t"); | ||
196 | hexprint (str, buffer, size); | ||
197 | adds (str, "\n"); | ||
198 | |||
199 | gnutls_free (buffer); | ||
200 | } | ||
201 | |||
202 | static void | ||
203 | print_key_usage (gnutls_string * str, gnutls_x509_crt_t cert) | ||
204 | { | ||
205 | unsigned int key_usage; | ||
206 | int err; | ||
207 | |||
208 | err = gnutls_x509_crt_get_key_usage (cert, &key_usage, NULL); | ||
209 | if (err < 0) | ||
210 | { | ||
211 | addf (str, "error: get_key_usage: %s\n", gnutls_strerror (err)); | ||
212 | return; | ||
213 | } | ||
214 | |||
215 | if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) | ||
216 | addf (str, _("\t\t\tDigital signature.\n")); | ||
217 | if (key_usage & GNUTLS_KEY_NON_REPUDIATION) | ||
218 | addf (str, _("\t\t\tNon repudiation.\n")); | ||
219 | if (key_usage & GNUTLS_KEY_KEY_ENCIPHERMENT) | ||
220 | addf (str, _("\t\t\tKey encipherment.\n")); | ||
221 | if (key_usage & GNUTLS_KEY_DATA_ENCIPHERMENT) | ||
222 | addf (str, _("\t\t\tData encipherment.\n")); | ||
223 | if (key_usage & GNUTLS_KEY_KEY_AGREEMENT) | ||
224 | addf (str, _("\t\t\tKey agreement.\n")); | ||
225 | if (key_usage & GNUTLS_KEY_KEY_CERT_SIGN) | ||
226 | addf (str, _("\t\t\tCertificate signing.\n")); | ||
227 | if (key_usage & GNUTLS_KEY_CRL_SIGN) | ||
228 | addf (str, _("\t\t\tCRL signing.\n")); | ||
229 | if (key_usage & GNUTLS_KEY_ENCIPHER_ONLY) | ||
230 | addf (str, _("\t\t\tKey encipher only.\n")); | ||
231 | if (key_usage & GNUTLS_KEY_DECIPHER_ONLY) | ||
232 | addf (str, _("\t\t\tKey decipher only.\n")); | ||
233 | } | ||
234 | |||
235 | static void | ||
236 | print_crldist (gnutls_string * str, gnutls_x509_crt_t cert) | ||
237 | { | ||
238 | char *buffer = NULL; | ||
239 | size_t size; | ||
240 | int err; | ||
241 | int indx; | ||
242 | |||
243 | for (indx = 0;; indx++) | ||
244 | { | ||
245 | size = 0; | ||
246 | err = gnutls_x509_crt_get_crl_dist_points (cert, indx, buffer, &size, | ||
247 | NULL, NULL); | ||
248 | if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) | ||
249 | return; | ||
250 | if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) | ||
251 | { | ||
252 | addf (str, "error: get_crl_dist_points: %s\n", | ||
253 | gnutls_strerror (err)); | ||
254 | return; | ||
255 | } | ||
256 | |||
257 | buffer = gnutls_malloc (size); | ||
258 | if (!buffer) | ||
259 | { | ||
260 | addf (str, "error: malloc: %s\n", gnutls_strerror (err)); | ||
261 | return; | ||
262 | } | ||
263 | |||
264 | err = gnutls_x509_crt_get_crl_dist_points (cert, indx, buffer, &size, | ||
265 | NULL, NULL); | ||
266 | if (err < 0) | ||
267 | { | ||
268 | gnutls_free (buffer); | ||
269 | addf (str, "error: get_crl_dist_points2: %s\n", | ||
270 | gnutls_strerror (err)); | ||
271 | return; | ||
272 | } | ||
273 | |||
274 | switch (err) | ||
275 | { | ||
276 | case GNUTLS_SAN_DNSNAME: | ||
277 | addf (str, "\t\t\tDNSname: %.*s\n", size, buffer); | ||
278 | break; | ||
279 | |||
280 | case GNUTLS_SAN_RFC822NAME: | ||
281 | addf (str, "\t\t\tRFC822name: %.*s\n", size, buffer); | ||
282 | break; | ||
283 | |||
284 | case GNUTLS_SAN_URI: | ||
285 | addf (str, "\t\t\tURI: %.*s\n", size, buffer); | ||
286 | break; | ||
287 | |||
288 | case GNUTLS_SAN_IPADDRESS: | ||
289 | addf (str, "\t\t\tIPAddress: %.*s\n", size, buffer); | ||
290 | break; | ||
291 | |||
292 | case GNUTLS_SAN_DN: | ||
293 | addf (str, "\t\t\tdirectoryName: %.*s\n", size, buffer); | ||
294 | break; | ||
295 | |||
296 | default: | ||
297 | addf (str, "error: unknown SAN\n"); | ||
298 | break; | ||
299 | } | ||
300 | gnutls_free (buffer); | ||
301 | } | ||
302 | } | ||
303 | |||
304 | static void | ||
305 | print_key_purpose (gnutls_string * str, gnutls_x509_crt_t cert) | ||
306 | { | ||
307 | int indx; | ||
308 | char *buffer = NULL; | ||
309 | size_t size; | ||
310 | int err; | ||
311 | |||
312 | for (indx = 0;; indx++) | ||
313 | { | ||
314 | size = 0; | ||
315 | err = gnutls_x509_crt_get_key_purpose_oid (cert, indx, buffer, | ||
316 | &size, NULL); | ||
317 | if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) | ||
318 | return; | ||
319 | if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) | ||
320 | { | ||
321 | addf (str, "error: get_key_purpose_oid: %s\n", | ||
322 | gnutls_strerror (err)); | ||
323 | return; | ||
324 | } | ||
325 | |||
326 | buffer = gnutls_malloc (size); | ||
327 | if (!buffer) | ||
328 | { | ||
329 | addf (str, "error: malloc: %s\n", gnutls_strerror (err)); | ||
330 | return; | ||
331 | } | ||
332 | |||
333 | err = gnutls_x509_crt_get_key_purpose_oid (cert, indx, buffer, | ||
334 | &size, NULL); | ||
335 | if (err < 0) | ||
336 | { | ||
337 | gnutls_free (buffer); | ||
338 | addf (str, "error: get_key_purpose_oid2: %s\n", | ||
339 | gnutls_strerror (err)); | ||
340 | return; | ||
341 | } | ||
342 | |||
343 | if (strcmp (buffer, GNUTLS_KP_TLS_WWW_SERVER) == 0) | ||
344 | addf (str, _("\t\t\tTLS WWW Server.\n")); | ||
345 | else if (strcmp (buffer, GNUTLS_KP_TLS_WWW_CLIENT) == 0) | ||
346 | addf (str, _("\t\t\tTLS WWW Client.\n")); | ||
347 | else if (strcmp (buffer, GNUTLS_KP_CODE_SIGNING) == 0) | ||
348 | addf (str, _("\t\t\tCode signing.\n")); | ||
349 | else if (strcmp (buffer, GNUTLS_KP_EMAIL_PROTECTION) == 0) | ||
350 | addf (str, _("\t\t\tEmail protection.\n")); | ||
351 | else if (strcmp (buffer, GNUTLS_KP_TIME_STAMPING) == 0) | ||
352 | addf (str, _("\t\t\tTime stamping.\n")); | ||
353 | else if (strcmp (buffer, GNUTLS_KP_OCSP_SIGNING) == 0) | ||
354 | addf (str, _("\t\t\tOCSP signing.\n")); | ||
355 | else if (strcmp (buffer, GNUTLS_KP_ANY) == 0) | ||
356 | addf (str, _("\t\t\tAny purpose.\n")); | ||
357 | else | ||
358 | addf (str, "\t\t\t%s\n", buffer); | ||
359 | |||
360 | gnutls_free (buffer); | ||
361 | } | ||
362 | } | ||
363 | |||
364 | static void | ||
365 | print_basic (gnutls_string * str, gnutls_x509_crt_t cert) | ||
366 | { | ||
367 | int pathlen; | ||
368 | int err; | ||
369 | |||
370 | err = gnutls_x509_crt_get_basic_constraints (cert, NULL, NULL, &pathlen); | ||
371 | if (err < 0) | ||
372 | { | ||
373 | addf (str, "error: get_basic_constraints: %s\n", gnutls_strerror (err)); | ||
374 | return; | ||
375 | } | ||
376 | |||
377 | if (err == 0) | ||
378 | addf (str, _("\t\t\tCertificate Authority (CA): FALSE\n")); | ||
379 | else | ||
380 | addf (str, _("\t\t\tCertificate Authority (CA): TRUE\n")); | ||
381 | |||
382 | if (pathlen >= 0) | ||
383 | addf (str, _("\t\t\tPath Length Constraint: %d\n"), pathlen); | ||
384 | } | ||
385 | |||
386 | static void | ||
387 | print_san (gnutls_string * str, gnutls_x509_crt_t cert) | ||
388 | { | ||
389 | unsigned int san_idx; | ||
390 | |||
391 | for (san_idx = 0;; san_idx++) | ||
392 | { | ||
393 | char *buffer = NULL; | ||
394 | size_t size = 0; | ||
395 | int err; | ||
396 | |||
397 | err = | ||
398 | gnutls_x509_crt_get_subject_alt_name (cert, san_idx, buffer, &size, | ||
399 | NULL); | ||
400 | if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) | ||
401 | break; | ||
402 | if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) | ||
403 | { | ||
404 | addf (str, "error: get_subject_alt_name: %s\n", | ||
405 | gnutls_strerror (err)); | ||
406 | return; | ||
407 | } | ||
408 | |||
409 | buffer = gnutls_malloc (size); | ||
410 | if (!buffer) | ||
411 | { | ||
412 | addf (str, "error: malloc: %s\n", gnutls_strerror (err)); | ||
413 | return; | ||
414 | } | ||
415 | |||
416 | err = gnutls_x509_crt_get_subject_alt_name (cert, san_idx, | ||
417 | buffer, &size, NULL); | ||
418 | if (err < 0) | ||
419 | { | ||
420 | gnutls_free (buffer); | ||
421 | addf (str, "error: get_subject_alt_name2: %s\n", | ||
422 | gnutls_strerror (err)); | ||
423 | return; | ||
424 | } | ||
425 | |||
426 | switch (err) | ||
427 | { | ||
428 | case GNUTLS_SAN_DNSNAME: | ||
429 | addf (str, "\t\t\tDNSname: %.*s\n", size, buffer); | ||
430 | break; | ||
431 | |||
432 | case GNUTLS_SAN_RFC822NAME: | ||
433 | addf (str, "\t\t\tRFC822name: %.*s\n", size, buffer); | ||
434 | break; | ||
435 | |||
436 | case GNUTLS_SAN_URI: | ||
437 | addf (str, "\t\t\tURI: %.*s\n", size, buffer); | ||
438 | break; | ||
439 | |||
440 | case GNUTLS_SAN_IPADDRESS: | ||
441 | addf (str, "\t\t\tIPAddress: %.*s\n", size, buffer); | ||
442 | break; | ||
443 | |||
444 | case GNUTLS_SAN_DN: | ||
445 | addf (str, "\t\t\tdirectoryName: %.*s\n", size, buffer); | ||
446 | break; | ||
447 | |||
448 | case GNUTLS_SAN_OTHERNAME: | ||
449 | { | ||
450 | char *oid = NULL; | ||
451 | size_t oidsize; | ||
452 | |||
453 | oidsize = 0; | ||
454 | err = gnutls_x509_crt_get_subject_alt_othername_oid | ||
455 | (cert, san_idx, oid, &oidsize); | ||
456 | if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) | ||
457 | { | ||
458 | gnutls_free (buffer); | ||
459 | addf (str, "error: get_subject_alt_othername_oid: %s\n", | ||
460 | gnutls_strerror (err)); | ||
461 | return; | ||
462 | } | ||
463 | |||
464 | oid = gnutls_malloc (oidsize); | ||
465 | if (!oid) | ||
466 | { | ||
467 | gnutls_free (buffer); | ||
468 | addf (str, "error: malloc: %s\n", gnutls_strerror (err)); | ||
469 | return; | ||
470 | } | ||
471 | |||
472 | err = gnutls_x509_crt_get_subject_alt_othername_oid | ||
473 | (cert, san_idx, oid, &oidsize); | ||
474 | if (err < 0) | ||
475 | { | ||
476 | gnutls_free (buffer); | ||
477 | gnutls_free (oid); | ||
478 | addf (str, "error: get_subject_alt_othername_oid2: %s\n", | ||
479 | gnutls_strerror (err)); | ||
480 | return; | ||
481 | } | ||
482 | |||
483 | if (err == GNUTLS_SAN_OTHERNAME_XMPP) | ||
484 | addf (str, _("\t\t\tXMPP Address: %.*s\n"), size, buffer); | ||
485 | else | ||
486 | { | ||
487 | addf (str, _("\t\t\totherName OID: %.*s\n"), oidsize, oid); | ||
488 | addf (str, _("\t\t\totherName DER: ")); | ||
489 | hexprint (str, buffer, size); | ||
490 | addf (str, _("\n\t\t\totherName ASCII: ")); | ||
491 | asciiprint (str, buffer, size); | ||
492 | addf (str, "\n"); | ||
493 | } | ||
494 | gnutls_free (oid); | ||
495 | } | ||
496 | break; | ||
497 | |||
498 | default: | ||
499 | addf (str, "error: unknown SAN\n"); | ||
500 | break; | ||
501 | } | ||
502 | |||
503 | gnutls_free (buffer); | ||
504 | } | ||
505 | } | ||
506 | |||
507 | static void | ||
508 | print_cert (gnutls_string * str, gnutls_x509_crt_t cert, int notsigned) | ||
509 | { | ||
510 | /* Version. */ | ||
511 | { | ||
512 | int version = gnutls_x509_crt_get_version (cert); | ||
513 | if (version < 0) | ||
514 | addf (str, "error: get_version: %s\n", gnutls_strerror (version)); | ||
515 | else | ||
516 | addf (str, _("\tVersion: %d\n"), version); | ||
517 | } | ||
518 | |||
519 | /* Serial. */ | ||
520 | { | ||
521 | char serial[128]; | ||
522 | size_t serial_size = sizeof (serial); | ||
523 | int err; | ||
524 | |||
525 | err = gnutls_x509_crt_get_serial (cert, serial, &serial_size); | ||
526 | if (err < 0) | ||
527 | addf (str, "error: get_serial: %s\n", gnutls_strerror (err)); | ||
528 | else | ||
529 | { | ||
530 | addf (str, _("\tSerial Number (hex): ")); | ||
531 | hexprint (str, serial, serial_size); | ||
532 | addf (str, "\n"); | ||
533 | } | ||
534 | } | ||
535 | |||
536 | /* Issuer. */ | ||
537 | if (!notsigned) | ||
538 | { | ||
539 | char dn[1024]; | ||
540 | size_t dn_size = sizeof (dn); | ||
541 | int err; | ||
542 | |||
543 | err = gnutls_x509_crt_get_issuer_dn (cert, dn, &dn_size); | ||
544 | if (err < 0) | ||
545 | addf (str, "error: get_issuer_dn: %s\n", gnutls_strerror (err)); | ||
546 | else | ||
547 | addf (str, _("\tIssuer: %s\n"), dn); | ||
548 | } | ||
549 | |||
550 | /* Validity. */ | ||
551 | { | ||
552 | time_t tim; | ||
553 | |||
554 | addf (str, _("\tValidity:\n")); | ||
555 | |||
556 | tim = gnutls_x509_crt_get_activation_time (cert); | ||
557 | { | ||
558 | char s[42]; | ||
559 | size_t max = sizeof (s); | ||
560 | struct tm t; | ||
561 | |||
562 | if (gmtime_r (&tim, &t) == NULL) | ||
563 | addf (str, "error: gmtime_r (%d)\n", t); | ||
564 | else if (strftime (s, max, "%a %b %e %H:%M:%S UTC %Y", &t) == 0) | ||
565 | addf (str, "error: strftime (%d)\n", t); | ||
566 | else | ||
567 | addf (str, _("\t\tNot Before: %s\n"), s); | ||
568 | } | ||
569 | |||
570 | tim = gnutls_x509_crt_get_expiration_time (cert); | ||
571 | { | ||
572 | char s[42]; | ||
573 | size_t max = sizeof (s); | ||
574 | struct tm t; | ||
575 | |||
576 | if (gmtime_r (&tim, &t) == NULL) | ||
577 | addf (str, "error: gmtime_r (%d)\n", t); | ||
578 | else if (strftime (s, max, "%a %b %e %H:%M:%S UTC %Y", &t) == 0) | ||
579 | addf (str, "error: strftime (%d)\n", t); | ||
580 | else | ||
581 | addf (str, _("\t\tNot After: %s\n"), s); | ||
582 | } | ||
583 | } | ||
584 | |||
585 | /* Subject. */ | ||
586 | { | ||
587 | char dn[1024]; | ||
588 | size_t dn_size = sizeof (dn); | ||
589 | int err; | ||
590 | |||
591 | err = gnutls_x509_crt_get_dn (cert, dn, &dn_size); | ||
592 | if (err < 0) | ||
593 | addf (str, "error: get_dn: %s\n", gnutls_strerror (err)); | ||
594 | else | ||
595 | addf (str, _("\tSubject: %s\n"), dn); | ||
596 | } | ||
597 | |||
598 | /* SubjectPublicKeyInfo. */ | ||
599 | { | ||
600 | int err; | ||
601 | unsigned int bits; | ||
602 | |||
603 | err = gnutls_x509_crt_get_pk_algorithm (cert, &bits); | ||
604 | if (err < 0) | ||
605 | addf (str, "error: get_pk_algorithm: %s\n", gnutls_strerror (err)); | ||
606 | else | ||
607 | { | ||
608 | const char *name = gnutls_pk_algorithm_get_name (err); | ||
609 | if (name == NULL) | ||
610 | name = "Unknown"; | ||
611 | |||
612 | addf (str, _("\tSubject Public Key Algorithm: %s\n"), name); | ||
613 | switch (err) | ||
614 | { | ||
615 | case GNUTLS_PK_RSA: | ||
616 | { | ||
617 | gnutls_datum_t m, e; | ||
618 | |||
619 | err = gnutls_x509_crt_get_pk_rsa_raw (cert, &m, &e); | ||
620 | if (err < 0) | ||
621 | addf (str, "error: get_pk_rsa_raw: %s\n", | ||
622 | gnutls_strerror (err)); | ||
623 | else | ||
624 | { | ||
625 | addf (str, _("\t\tModulus (bits %d):\n"), bits); | ||
626 | hexdump (str, m.data, m.size, "\t\t\t"); | ||
627 | addf (str, _("\t\tExponent:\n")); | ||
628 | hexdump (str, e.data, e.size, "\t\t\t"); | ||
629 | } | ||
630 | |||
631 | gnutls_free (m.data); | ||
632 | gnutls_free (e.data); | ||
633 | } | ||
634 | break; | ||
635 | |||
636 | case GNUTLS_PK_DSA: | ||
637 | { | ||
638 | gnutls_datum_t p, q, g, y; | ||
639 | |||
640 | err = gnutls_x509_crt_get_pk_dsa_raw (cert, &p, &q, &g, &y); | ||
641 | if (err < 0) | ||
642 | addf (str, "error: get_pk_dsa_raw: %s\n", | ||
643 | gnutls_strerror (err)); | ||
644 | else | ||
645 | { | ||
646 | addf (str, _("\t\tPublic key (bits %d):\n"), bits); | ||
647 | hexdump (str, y.data, y.size, "\t\t\t"); | ||
648 | addf (str, _("\t\tP:\n")); | ||
649 | hexdump (str, p.data, p.size, "\t\t\t"); | ||
650 | addf (str, _("\t\tQ:\n")); | ||
651 | hexdump (str, q.data, q.size, "\t\t\t"); | ||
652 | addf (str, _("\t\tG:\n")); | ||
653 | hexdump (str, g.data, g.size, "\t\t\t"); | ||
654 | } | ||
655 | } | ||
656 | break; | ||
657 | |||
658 | default: | ||
659 | break; | ||
660 | } | ||
661 | } | ||
662 | } | ||
663 | |||
664 | /* Extensions. */ | ||
665 | if (gnutls_x509_crt_get_version (cert) >= 3) | ||
666 | { | ||
667 | size_t i; | ||
668 | int err = 0; | ||
669 | |||
670 | for (i = 0;; i++) | ||
671 | { | ||
672 | char oid[128] = ""; | ||
673 | size_t sizeof_oid = sizeof (oid); | ||
674 | int critical; | ||
675 | size_t san_idx = 0; | ||
676 | size_t proxy_idx = 0; | ||
677 | size_t basic_idx = 0; | ||
678 | size_t keyusage_idx = 0; | ||
679 | size_t keypurpose_idx = 0; | ||
680 | size_t ski_idx = 0; | ||
681 | size_t aki_idx = 0; | ||
682 | size_t crldist_idx = 0; | ||
683 | |||
684 | err = gnutls_x509_crt_get_extension_info (cert, i, | ||
685 | oid, &sizeof_oid, | ||
686 | &critical); | ||
687 | if (err < 0) | ||
688 | { | ||
689 | if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) | ||
690 | break; | ||
691 | addf (str, "error: get_extension_info: %s\n", | ||
692 | gnutls_strerror (err)); | ||
693 | continue; | ||
694 | } | ||
695 | |||
696 | if (i == 0) | ||
697 | addf (str, _("\tExtensions:\n")); | ||
698 | |||
699 | if (strcmp (oid, "2.5.29.19") == 0) | ||
700 | { | ||
701 | if (basic_idx) | ||
702 | { | ||
703 | addf (str, "error: more than one basic constraint\n"); | ||
704 | continue; | ||
705 | } | ||
706 | |||
707 | addf (str, _("\t\tBasic Constraints (%s):\n"), | ||
708 | critical ? _("critical") : _("not critical")); | ||
709 | |||
710 | print_basic (str, cert); | ||
711 | |||
712 | basic_idx++; | ||
713 | } | ||
714 | else if (strcmp (oid, "2.5.29.14") == 0) | ||
715 | { | ||
716 | if (ski_idx) | ||
717 | { | ||
718 | addf (str, "error: more than one SKI extension\n"); | ||
719 | continue; | ||
720 | } | ||
721 | |||
722 | addf (str, _("\t\tSubject Key Identifier (%s):\n"), | ||
723 | critical ? _("critical") : _("not critical")); | ||
724 | |||
725 | print_ski (str, cert); | ||
726 | |||
727 | ski_idx++; | ||
728 | } | ||
729 | else if (strcmp (oid, "2.5.29.35") == 0) | ||
730 | { | ||
731 | if (aki_idx) | ||
732 | { | ||
733 | addf (str, "error: more than one AKI extension\n"); | ||
734 | continue; | ||
735 | } | ||
736 | |||
737 | addf (str, _("\t\tAuthority Key Identifier (%s):\n"), | ||
738 | critical ? _("critical") : _("not critical")); | ||
739 | |||
740 | print_aki (str, cert); | ||
741 | |||
742 | aki_idx++; | ||
743 | } | ||
744 | else if (strcmp (oid, "2.5.29.15") == 0) | ||
745 | { | ||
746 | if (keyusage_idx) | ||
747 | { | ||
748 | addf (str, "error: more than one key usage extension\n"); | ||
749 | continue; | ||
750 | } | ||
751 | |||
752 | addf (str, _("\t\tKey Usage (%s):\n"), | ||
753 | critical ? _("critical") : _("not critical")); | ||
754 | |||
755 | print_key_usage (str, cert); | ||
756 | |||
757 | keyusage_idx++; | ||
758 | } | ||
759 | else if (strcmp (oid, "2.5.29.37") == 0) | ||
760 | { | ||
761 | if (keypurpose_idx) | ||
762 | { | ||
763 | addf (str, "error: more than one key purpose extension\n"); | ||
764 | continue; | ||
765 | } | ||
766 | |||
767 | addf (str, _("\t\tKey Purpose (%s):\n"), | ||
768 | critical ? _("critical") : _("not critical")); | ||
769 | |||
770 | print_key_purpose (str, cert); | ||
771 | |||
772 | keypurpose_idx++; | ||
773 | } | ||
774 | else if (strcmp (oid, "2.5.29.17") == 0) | ||
775 | { | ||
776 | if (san_idx) | ||
777 | { | ||
778 | addf (str, "error: more than one SKI extension\n"); | ||
779 | continue; | ||
780 | } | ||
781 | |||
782 | addf (str, _("\t\tSubject Alternative Name (%s):\n"), | ||
783 | critical ? _("critical") : _("not critical")); | ||
784 | |||
785 | print_san (str, cert); | ||
786 | |||
787 | san_idx++; | ||
788 | } | ||
789 | else if (strcmp (oid, "2.5.29.31") == 0) | ||
790 | { | ||
791 | if (crldist_idx) | ||
792 | { | ||
793 | addf (str, "error: more than one CRL distribution point\n"); | ||
794 | continue; | ||
795 | } | ||
796 | |||
797 | addf (str, _("\t\tCRL Distribution points (%s):\n"), | ||
798 | critical ? _("critical") : _("not critical")); | ||
799 | |||
800 | print_crldist (str, cert); | ||
801 | |||
802 | crldist_idx++; | ||
803 | } | ||
804 | else if (strcmp (oid, "1.3.6.1.5.5.7.1.14") == 0) | ||
805 | { | ||
806 | if (proxy_idx) | ||
807 | { | ||
808 | addf (str, "error: more than one proxy extension\n"); | ||
809 | continue; | ||
810 | } | ||
811 | |||
812 | addf (str, _("\t\tProxy Certificate Information (%s):\n"), | ||
813 | critical ? _("critical") : _("not critical")); | ||
814 | |||
815 | print_proxy (str, cert); | ||
816 | |||
817 | proxy_idx++; | ||
818 | } | ||
819 | else | ||
820 | { | ||
821 | char *buffer; | ||
822 | size_t extlen = 0; | ||
823 | |||
824 | addf (str, _("\t\tUnknown extension %s (%s):\n"), oid, | ||
825 | critical ? _("critical") : _("not critical")); | ||
826 | |||
827 | err = gnutls_x509_crt_get_extension_data (cert, i, | ||
828 | NULL, &extlen); | ||
829 | if (err < 0) | ||
830 | { | ||
831 | addf (str, "error: get_extension_data: %s\n", | ||
832 | gnutls_strerror (err)); | ||
833 | continue; | ||
834 | } | ||
835 | |||
836 | buffer = gnutls_malloc (extlen); | ||
837 | if (!buffer) | ||
838 | { | ||
839 | addf (str, "error: malloc: %s\n", gnutls_strerror (err)); | ||
840 | continue; | ||
841 | } | ||
842 | |||
843 | err = gnutls_x509_crt_get_extension_data (cert, i, | ||
844 | buffer, &extlen); | ||
845 | if (err < 0) | ||
846 | { | ||
847 | gnutls_free (buffer); | ||
848 | addf (str, "error: get_extension_data2: %s\n", | ||
849 | gnutls_strerror (err)); | ||
850 | continue; | ||
851 | } | ||
852 | |||
853 | addf (str, _("\t\t\tASCII: ")); | ||
854 | asciiprint (str, buffer, extlen); | ||
855 | addf (str, "\n"); | ||
856 | |||
857 | addf (str, _("\t\t\tHexdump: ")); | ||
858 | hexprint (str, buffer, extlen); | ||
859 | adds (str, "\n"); | ||
860 | |||
861 | gnutls_free (buffer); | ||
862 | } | ||
863 | } | ||
864 | } | ||
865 | |||
866 | /* Signature. */ | ||
867 | if (!notsigned) | ||
868 | { | ||
869 | int err; | ||
870 | size_t size = 0; | ||
871 | char *buffer = NULL; | ||
872 | |||
873 | err = gnutls_x509_crt_get_signature_algorithm (cert); | ||
874 | if (err < 0) | ||
875 | addf (str, "error: get_signature_algorithm: %s\n", | ||
876 | gnutls_strerror (err)); | ||
877 | else | ||
878 | { | ||
879 | const char *name = gnutls_sign_algorithm_get_name (err); | ||
880 | if (name == NULL) | ||
881 | name = "Unknown"; | ||
882 | addf (str, _("\tSignature Algorithm: %s\n"), name); | ||
883 | } | ||
884 | if (err == GNUTLS_SIGN_RSA_MD5 || err == GNUTLS_SIGN_RSA_MD2) | ||
885 | { | ||
886 | addf (str, | ||
887 | _ | ||
888 | ("warning: signed using a broken signature algorithm that can be forged.\n")); | ||
889 | } | ||
890 | |||
891 | err = gnutls_x509_crt_get_signature (cert, buffer, &size); | ||
892 | if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) | ||
893 | { | ||
894 | addf (str, "error: get_signature: %s\n", gnutls_strerror (err)); | ||
895 | return; | ||
896 | } | ||
897 | |||
898 | buffer = gnutls_malloc (size); | ||
899 | if (!buffer) | ||
900 | { | ||
901 | addf (str, "error: malloc: %s\n", gnutls_strerror (err)); | ||
902 | return; | ||
903 | } | ||
904 | |||
905 | err = gnutls_x509_crt_get_signature (cert, buffer, &size); | ||
906 | if (err < 0) | ||
907 | { | ||
908 | gnutls_free (buffer); | ||
909 | addf (str, "error: get_signature2: %s\n", gnutls_strerror (err)); | ||
910 | return; | ||
911 | } | ||
912 | |||
913 | addf (str, _("\tSignature:\n")); | ||
914 | hexdump (str, buffer, size, "\t\t"); | ||
915 | |||
916 | gnutls_free (buffer); | ||
917 | } | ||
918 | } | ||
919 | |||
920 | static void | ||
921 | print_fingerprint (gnutls_string * str, gnutls_x509_crt_t cert, | ||
922 | gnutls_digest_algorithm_t algo) | ||
923 | { | ||
924 | int err; | ||
925 | char buffer[MAX_HASH_SIZE]; | ||
926 | size_t size = sizeof (buffer); | ||
927 | |||
928 | err = gnutls_x509_crt_get_fingerprint (cert, algo, buffer, &size); | ||
929 | if (err < 0) | ||
930 | { | ||
931 | addf (str, "error: get_fingerprint: %s\n", gnutls_strerror (err)); | ||
932 | return; | ||
933 | } | ||
934 | |||
935 | if (algo == GNUTLS_DIG_MD5) | ||
936 | addf (str, _("\tMD5 fingerprint:\n\t\t")); | ||
937 | else | ||
938 | addf (str, _("\tSHA-1 fingerprint:\n\t\t")); | ||
939 | hexprint (str, buffer, size); | ||
940 | adds (str, "\n"); | ||
941 | } | ||
942 | |||
943 | static void | ||
944 | print_keyid (gnutls_string * str, gnutls_x509_crt_t cert) | ||
945 | { | ||
946 | int err; | ||
947 | size_t size = 0; | ||
948 | char *buffer = NULL; | ||
949 | |||
950 | err = gnutls_x509_crt_get_key_id (cert, 0, buffer, &size); | ||
951 | if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) | ||
952 | { | ||
953 | addf (str, "error: get_key_id: %s\n", gnutls_strerror (err)); | ||
954 | return; | ||
955 | } | ||
956 | |||
957 | buffer = gnutls_malloc (size); | ||
958 | if (!buffer) | ||
959 | { | ||
960 | addf (str, "error: malloc: %s\n", gnutls_strerror (err)); | ||
961 | return; | ||
962 | } | ||
963 | |||
964 | err = gnutls_x509_crt_get_key_id (cert, 0, buffer, &size); | ||
965 | if (err < 0) | ||
966 | { | ||
967 | gnutls_free (buffer); | ||
968 | addf (str, "error: get_key_id2: %s\n", gnutls_strerror (err)); | ||
969 | return; | ||
970 | } | ||
971 | |||
972 | addf (str, _("\tPublic Key Id:\n\t\t")); | ||
973 | hexprint (str, buffer, size); | ||
974 | adds (str, "\n"); | ||
975 | |||
976 | gnutls_free (buffer); | ||
977 | } | ||
978 | |||
979 | static void | ||
980 | print_other (gnutls_string * str, gnutls_x509_crt_t cert, int notsigned) | ||
981 | { | ||
982 | if (!notsigned) | ||
983 | { | ||
984 | print_fingerprint (str, cert, GNUTLS_DIG_MD5); | ||
985 | print_fingerprint (str, cert, GNUTLS_DIG_SHA1); | ||
986 | } | ||
987 | print_keyid (str, cert); | ||
988 | } | ||
989 | |||
990 | static void | ||
991 | print_oneline (gnutls_string * str, gnutls_x509_crt_t cert) | ||
992 | { | ||
993 | |||
994 | /* Subject. */ | ||
995 | { | ||
996 | char dn[1024]; | ||
997 | size_t dn_size = sizeof (dn); | ||
998 | int err; | ||
999 | |||
1000 | err = gnutls_x509_crt_get_dn (cert, dn, &dn_size); | ||
1001 | if (err < 0) | ||
1002 | addf (str, "unknown subject (%s), ", gnutls_strerror (err)); | ||
1003 | else | ||
1004 | addf (str, "subject `%s', ", dn); | ||
1005 | } | ||
1006 | |||
1007 | /* Issuer. */ | ||
1008 | { | ||
1009 | char dn[1024]; | ||
1010 | size_t dn_size = sizeof (dn); | ||
1011 | int err; | ||
1012 | |||
1013 | err = gnutls_x509_crt_get_issuer_dn (cert, dn, &dn_size); | ||
1014 | if (err < 0) | ||
1015 | addf (str, "unknown issuer (%s), ", gnutls_strerror (err)); | ||
1016 | else | ||
1017 | addf (str, "issuer `%s', ", dn); | ||
1018 | } | ||
1019 | |||
1020 | { | ||
1021 | int bits; | ||
1022 | const char *name = gnutls_pk_algorithm_get_name | ||
1023 | (gnutls_x509_crt_get_pk_algorithm (cert, &bits)); | ||
1024 | if (name == NULL) | ||
1025 | name = "Unknown"; | ||
1026 | addf (str, "%s key %d bits, ", name, bits); | ||
1027 | } | ||
1028 | |||
1029 | /* Validity. */ | ||
1030 | { | ||
1031 | time_t tim; | ||
1032 | |||
1033 | tim = gnutls_x509_crt_get_activation_time (cert); | ||
1034 | { | ||
1035 | char s[42]; | ||
1036 | size_t max = sizeof (s); | ||
1037 | struct tm t; | ||
1038 | |||
1039 | if (gmtime_r (&tim, &t) == NULL) | ||
1040 | addf (str, "unknown activation (%d), ", t); | ||
1041 | else if (strftime (s, max, "%Y-%m-%d %H:%M:%S UTC", &t) == 0) | ||
1042 | addf (str, "failed activation (%d), ", t); | ||
1043 | else | ||
1044 | addf (str, "activated `%s', ", s); | ||
1045 | } | ||
1046 | |||
1047 | tim = gnutls_x509_crt_get_expiration_time (cert); | ||
1048 | { | ||
1049 | char s[42]; | ||
1050 | size_t max = sizeof (s); | ||
1051 | struct tm t; | ||
1052 | |||
1053 | if (gmtime_r (&tim, &t) == NULL) | ||
1054 | addf (str, "unknown expiry (%d), ", t); | ||
1055 | else if (strftime (s, max, "%Y-%m-%d %H:%M:%S UTC", &t) == 0) | ||
1056 | addf (str, "failed expiry (%d), ", t); | ||
1057 | else | ||
1058 | addf (str, "expires `%s', ", s); | ||
1059 | } | ||
1060 | } | ||
1061 | |||
1062 | { | ||
1063 | int pathlen; | ||
1064 | char *policyLanguage; | ||
1065 | int err; | ||
1066 | |||
1067 | err = gnutls_x509_crt_get_proxy (cert, NULL, | ||
1068 | &pathlen, &policyLanguage, NULL, NULL); | ||
1069 | if (err == 0) | ||
1070 | { | ||
1071 | addf (str, "proxy certificate (policy="); | ||
1072 | if (strcmp (policyLanguage, "1.3.6.1.5.5.7.21.1") == 0) | ||
1073 | addf (str, "id-ppl-inheritALL"); | ||
1074 | else if (strcmp (policyLanguage, "1.3.6.1.5.5.7.21.2") == 0) | ||
1075 | addf (str, "id-ppl-independent"); | ||
1076 | else | ||
1077 | addf (str, "%s", policyLanguage); | ||
1078 | if (pathlen >= 0) | ||
1079 | addf (str, ", pathlen=%d), ", pathlen); | ||
1080 | else | ||
1081 | addf (str, "), "); | ||
1082 | gnutls_free (policyLanguage); | ||
1083 | } | ||
1084 | } | ||
1085 | |||
1086 | { | ||
1087 | char buffer[20]; | ||
1088 | size_t size = sizeof (buffer); | ||
1089 | int err; | ||
1090 | |||
1091 | err = gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1, | ||
1092 | buffer, &size); | ||
1093 | if (err < 0) | ||
1094 | { | ||
1095 | addf (str, "unknown fingerprint (%s)", gnutls_strerror (err)); | ||
1096 | } | ||
1097 | else | ||
1098 | { | ||
1099 | addf (str, "SHA-1 fingerprint `"); | ||
1100 | hexprint (str, buffer, size); | ||
1101 | adds (str, "'"); | ||
1102 | } | ||
1103 | } | ||
1104 | |||
1105 | } | ||
1106 | |||
1107 | /** | ||
1108 | * gnutls_x509_crt_print - Pretty print X.509 certificates | ||
1109 | * @cert: The structure to be printed | ||
1110 | * @format: Indicate the format to use | ||
1111 | * @out: Newly allocated datum with zero terminated string. | ||
1112 | * | ||
1113 | * This function will pretty print a X.509 certificate, suitable for | ||
1114 | * display to a human. | ||
1115 | * | ||
1116 | * If the format is %GNUTLS_X509_CRT_FULL then all fields of the | ||
1117 | * certificate will be output, on multiple lines. The | ||
1118 | * %GNUTLS_X509_CRT_ONELINE format will generate one line with some | ||
1119 | * selected fields, which is useful for logging purposes. | ||
1120 | * | ||
1121 | * The output @out needs to be deallocate using gnutls_free(). | ||
1122 | * | ||
1123 | * Returns 0 on success. | ||
1124 | **/ | ||
1125 | int | ||
1126 | gnutls_x509_crt_print (gnutls_x509_crt_t cert, | ||
1127 | gnutls_certificate_print_formats_t format, | ||
1128 | gnutls_datum_t * out) | ||
1129 | { | ||
1130 | gnutls_string str; | ||
1131 | |||
1132 | if (format == GNUTLS_X509_CRT_FULL | ||
1133 | || format == GNUTLS_X509_CRT_UNSIGNED_FULL) | ||
1134 | { | ||
1135 | _gnutls_string_init (&str, gnutls_malloc, gnutls_realloc, gnutls_free); | ||
1136 | |||
1137 | _gnutls_string_append_str (&str, _("X.509 Certificate Information:\n")); | ||
1138 | |||
1139 | print_cert (&str, cert, format == GNUTLS_X509_CRT_UNSIGNED_FULL); | ||
1140 | |||
1141 | _gnutls_string_append_str (&str, _("Other Information:\n")); | ||
1142 | |||
1143 | print_other (&str, cert, format == GNUTLS_X509_CRT_UNSIGNED_FULL); | ||
1144 | |||
1145 | _gnutls_string_append_data (&str, "\0", 1); | ||
1146 | out->data = str.data; | ||
1147 | out->size = strlen (str.data); | ||
1148 | } | ||
1149 | else if (format == GNUTLS_X509_CRT_ONELINE) | ||
1150 | { | ||
1151 | _gnutls_string_init (&str, gnutls_malloc, gnutls_realloc, gnutls_free); | ||
1152 | |||
1153 | print_oneline (&str, cert); | ||
1154 | |||
1155 | _gnutls_string_append_data (&str, "\0", 1); | ||
1156 | out->data = str.data; | ||
1157 | out->size = strlen (str.data); | ||
1158 | } | ||
1159 | else | ||
1160 | { | ||
1161 | gnutls_assert (); | ||
1162 | return GNUTLS_E_INVALID_REQUEST; | ||
1163 | } | ||
1164 | |||
1165 | return 0; | ||
1166 | } | ||
1167 | |||
1168 | static void | ||
1169 | print_crl (gnutls_string * str, gnutls_x509_crl_t crl, int notsigned) | ||
1170 | { | ||
1171 | /* Version. */ | ||
1172 | { | ||
1173 | int version = gnutls_x509_crl_get_version (crl); | ||
1174 | if (version == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) | ||
1175 | addf (str, _("\tVersion: 1 (default)\n")); | ||
1176 | else if (version < 0) | ||
1177 | addf (str, "error: get_version: %s\n", gnutls_strerror (version)); | ||
1178 | else | ||
1179 | addf (str, _("\tVersion: %d\n"), version); | ||
1180 | } | ||
1181 | |||
1182 | /* Issuer. */ | ||
1183 | if (!notsigned) | ||
1184 | { | ||
1185 | char dn[1024]; | ||
1186 | size_t dn_size = sizeof (dn); | ||
1187 | int err; | ||
1188 | |||
1189 | err = gnutls_x509_crl_get_issuer_dn (crl, dn, &dn_size); | ||
1190 | if (err < 0) | ||
1191 | addf (str, "error: get_issuer_dn: %s\n", gnutls_strerror (err)); | ||
1192 | else | ||
1193 | addf (str, _("\tIssuer: %s\n"), dn); | ||
1194 | } | ||
1195 | |||
1196 | /* Validity. */ | ||
1197 | { | ||
1198 | time_t tim; | ||
1199 | |||
1200 | addf (str, _("\tUpdate dates:\n")); | ||
1201 | |||
1202 | tim = gnutls_x509_crl_get_this_update (crl); | ||
1203 | { | ||
1204 | char s[42]; | ||
1205 | size_t max = sizeof (s); | ||
1206 | struct tm t; | ||
1207 | |||
1208 | if (gmtime_r (&tim, &t) == NULL) | ||
1209 | addf (str, "error: gmtime_r (%d)\n", t); | ||
1210 | else if (strftime (s, max, "%a %b %e %H:%M:%S UTC %Y", &t) == 0) | ||
1211 | addf (str, "error: strftime (%d)\n", t); | ||
1212 | else | ||
1213 | addf (str, _("\t\tIssued: %s\n"), s); | ||
1214 | } | ||
1215 | |||
1216 | tim = gnutls_x509_crl_get_next_update (crl); | ||
1217 | { | ||
1218 | char s[42]; | ||
1219 | size_t max = sizeof (s); | ||
1220 | struct tm t; | ||
1221 | |||
1222 | if (tim == -1) | ||
1223 | addf (str, "\t\tNo next update time.\n"); | ||
1224 | else if (gmtime_r (&tim, &t) == NULL) | ||
1225 | addf (str, "error: gmtime_r (%d)\n", t); | ||
1226 | else if (strftime (s, max, "%a %b %e %H:%M:%S UTC %Y", &t) == 0) | ||
1227 | addf (str, "error: strftime (%d)\n", t); | ||
1228 | else | ||
1229 | addf (str, _("\t\tNext at: %s\n"), s); | ||
1230 | } | ||
1231 | } | ||
1232 | |||
1233 | /* Revoked certificates. */ | ||
1234 | { | ||
1235 | int num = gnutls_x509_crl_get_crt_count (crl); | ||
1236 | int j; | ||
1237 | |||
1238 | if (num) | ||
1239 | addf (str, _("\tRevoked certificates (%d):\n"), num); | ||
1240 | else | ||
1241 | addf (str, _("\tNo revoked certificates.\n")); | ||
1242 | |||
1243 | for (j = 0; j < num; j++) | ||
1244 | { | ||
1245 | char serial[128]; | ||
1246 | size_t serial_size = sizeof (serial); | ||
1247 | int err; | ||
1248 | time_t tim; | ||
1249 | |||
1250 | err = gnutls_x509_crl_get_crt_serial (crl, j, serial, | ||
1251 | &serial_size, &tim); | ||
1252 | if (err < 0) | ||
1253 | addf (str, "error: get_crt_serial: %s\n", gnutls_strerror (err)); | ||
1254 | else | ||
1255 | { | ||
1256 | char s[42]; | ||
1257 | size_t max = sizeof (s); | ||
1258 | struct tm t; | ||
1259 | |||
1260 | addf (str, _("\t\tSerial Number (hex): ")); | ||
1261 | hexprint (str, serial, serial_size); | ||
1262 | adds (str, "\n"); | ||
1263 | |||
1264 | if (gmtime_r (&tim, &t) == NULL) | ||
1265 | addf (str, "error: gmtime_r (%d)\n", t); | ||
1266 | else if (strftime (s, max, "%a %b %e %H:%M:%S UTC %Y", &t) == 0) | ||
1267 | addf (str, "error: strftime (%d)\n", t); | ||
1268 | else | ||
1269 | addf (str, _("\t\tRevoked at: %s\n"), s); | ||
1270 | } | ||
1271 | } | ||
1272 | } | ||
1273 | |||
1274 | /* Signature. */ | ||
1275 | if (!notsigned) | ||
1276 | { | ||
1277 | int err; | ||
1278 | size_t size = 0; | ||
1279 | char *buffer = NULL; | ||
1280 | |||
1281 | err = gnutls_x509_crl_get_signature_algorithm (crl); | ||
1282 | if (err < 0) | ||
1283 | addf (str, "error: get_signature_algorithm: %s\n", | ||
1284 | gnutls_strerror (err)); | ||
1285 | else | ||
1286 | { | ||
1287 | const char *name = gnutls_sign_algorithm_get_name (err); | ||
1288 | if (name == NULL) | ||
1289 | name = "Unknown"; | ||
1290 | addf (str, _("\tSignature Algorithm: %s\n"), name); | ||
1291 | } | ||
1292 | if (err == GNUTLS_SIGN_RSA_MD5 || err == GNUTLS_SIGN_RSA_MD2) | ||
1293 | { | ||
1294 | addf (str, | ||
1295 | _ | ||
1296 | ("warning: signed using a broken signature algorithm that can be forged.\n")); | ||
1297 | } | ||
1298 | |||
1299 | err = gnutls_x509_crl_get_signature (crl, buffer, &size); | ||
1300 | if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) | ||
1301 | { | ||
1302 | addf (str, "error: get_signature: %s\n", gnutls_strerror (err)); | ||
1303 | return; | ||
1304 | } | ||
1305 | |||
1306 | buffer = gnutls_malloc (size); | ||
1307 | if (!buffer) | ||
1308 | { | ||
1309 | addf (str, "error: malloc: %s\n", gnutls_strerror (err)); | ||
1310 | return; | ||
1311 | } | ||
1312 | |||
1313 | err = gnutls_x509_crl_get_signature (crl, buffer, &size); | ||
1314 | if (err < 0) | ||
1315 | { | ||
1316 | gnutls_free (buffer); | ||
1317 | addf (str, "error: get_signature2: %s\n", gnutls_strerror (err)); | ||
1318 | return; | ||
1319 | } | ||
1320 | |||
1321 | addf (str, _("\tSignature:\n")); | ||
1322 | hexdump (str, buffer, size, "\t\t"); | ||
1323 | |||
1324 | gnutls_free (buffer); | ||
1325 | } | ||
1326 | } | ||
1327 | |||
1328 | /** | ||
1329 | * gnutls_x509_crl_print - Pretty print X.509 certificate revocation list | ||
1330 | * @crl: The structure to be printed | ||
1331 | * @format: Indicate the format to use | ||
1332 | * @out: Newly allocated datum with zero terminated string. | ||
1333 | * | ||
1334 | * This function will pretty print a X.509 certificate revocation | ||
1335 | * list, suitable for display to a human. | ||
1336 | * | ||
1337 | * The output @out needs to be deallocate using gnutls_free(). | ||
1338 | * | ||
1339 | * Returns 0 on success. | ||
1340 | **/ | ||
1341 | int | ||
1342 | gnutls_x509_crl_print (gnutls_x509_crl_t crl, | ||
1343 | gnutls_certificate_print_formats_t format, | ||
1344 | gnutls_datum_t * out) | ||
1345 | { | ||
1346 | gnutls_string str; | ||
1347 | |||
1348 | _gnutls_string_init (&str, gnutls_malloc, gnutls_realloc, gnutls_free); | ||
1349 | |||
1350 | _gnutls_string_append_str | ||
1351 | (&str, _("X.509 Certificate Revocation List Information:\n")); | ||
1352 | |||
1353 | print_crl (&str, crl, format == GNUTLS_X509_CRT_UNSIGNED_FULL); | ||
1354 | |||
1355 | _gnutls_string_append_data (&str, "\0", 1); | ||
1356 | out->data = str.data; | ||
1357 | out->size = strlen (str.data); | ||
1358 | |||
1359 | return 0; | ||
1360 | } | ||
diff --git a/src/daemon/https/x509/pkcs12.c b/src/daemon/https/x509/pkcs12.c new file mode 100644 index 00000000..40f7a243 --- /dev/null +++ b/src/daemon/https/x509/pkcs12.c | |||
@@ -0,0 +1,1325 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | /* Functions that relate on PKCS12 packet parsing. | ||
26 | */ | ||
27 | |||
28 | #include <gnutls_int.h> | ||
29 | #include <libtasn1.h> | ||
30 | |||
31 | #ifdef ENABLE_PKI | ||
32 | |||
33 | #include <gnutls_datum.h> | ||
34 | #include <gnutls_global.h> | ||
35 | #include <gnutls_errors.h> | ||
36 | #include <gnutls_num.h> | ||
37 | #include <common.h> | ||
38 | #include <x509_b64.h> | ||
39 | #include <pkcs12.h> | ||
40 | #include <dn.h> | ||
41 | #include <mpi.h> | ||
42 | #include <gc.h> | ||
43 | |||
44 | |||
45 | /* Decodes the PKCS #12 auth_safe, and returns the allocated raw data, | ||
46 | * which holds them. Returns an ASN1_TYPE of authenticatedSafe. | ||
47 | */ | ||
48 | static int | ||
49 | _decode_pkcs12_auth_safe (ASN1_TYPE pkcs12, ASN1_TYPE * authen_safe, | ||
50 | gnutls_datum_t * raw) | ||
51 | { | ||
52 | char oid[128]; | ||
53 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
54 | gnutls_datum_t auth_safe = { NULL, 0 }; | ||
55 | int tmp_size, len, result; | ||
56 | |||
57 | len = sizeof (oid) - 1; | ||
58 | result = asn1_read_value (pkcs12, "authSafe.contentType", oid, &len); | ||
59 | if (result != ASN1_SUCCESS) | ||
60 | { | ||
61 | gnutls_assert (); | ||
62 | return _gnutls_asn2err (result); | ||
63 | } | ||
64 | |||
65 | if (strcmp (oid, DATA_OID) != 0) | ||
66 | { | ||
67 | gnutls_assert (); | ||
68 | _gnutls_x509_log ("Unknown PKCS12 Content OID '%s'\n", oid); | ||
69 | return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE; | ||
70 | } | ||
71 | |||
72 | /* Step 1. Read the content data | ||
73 | */ | ||
74 | |||
75 | tmp_size = 0; | ||
76 | result = | ||
77 | _gnutls_x509_read_value (pkcs12, "authSafe.content", &auth_safe, 1); | ||
78 | if (result < 0) | ||
79 | { | ||
80 | gnutls_assert (); | ||
81 | goto cleanup; | ||
82 | } | ||
83 | |||
84 | /* Step 2. Extract the authenticatedSafe. | ||
85 | */ | ||
86 | |||
87 | if ((result = asn1_create_element | ||
88 | (_gnutls_get_pkix (), "PKIX1.pkcs-12-AuthenticatedSafe", | ||
89 | &c2)) != ASN1_SUCCESS) | ||
90 | { | ||
91 | gnutls_assert (); | ||
92 | result = _gnutls_asn2err (result); | ||
93 | goto cleanup; | ||
94 | } | ||
95 | |||
96 | result = asn1_der_decoding (&c2, auth_safe.data, auth_safe.size, NULL); | ||
97 | if (result != ASN1_SUCCESS) | ||
98 | { | ||
99 | gnutls_assert (); | ||
100 | result = _gnutls_asn2err (result); | ||
101 | goto cleanup; | ||
102 | } | ||
103 | |||
104 | if (raw == NULL) | ||
105 | { | ||
106 | _gnutls_free_datum (&auth_safe); | ||
107 | } | ||
108 | else | ||
109 | { | ||
110 | raw->data = auth_safe.data; | ||
111 | raw->size = auth_safe.size; | ||
112 | } | ||
113 | |||
114 | if (authen_safe) | ||
115 | *authen_safe = c2; | ||
116 | else | ||
117 | asn1_delete_structure (&c2); | ||
118 | |||
119 | return 0; | ||
120 | |||
121 | cleanup: | ||
122 | if (c2) | ||
123 | asn1_delete_structure (&c2); | ||
124 | _gnutls_free_datum (&auth_safe); | ||
125 | return result; | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * gnutls_pkcs12_init - This function initializes a gnutls_pkcs12_t structure | ||
130 | * @pkcs12: The structure to be initialized | ||
131 | * | ||
132 | * This function will initialize a PKCS12 structure. PKCS12 structures | ||
133 | * usually contain lists of X.509 Certificates and X.509 Certificate | ||
134 | * revocation lists. | ||
135 | * | ||
136 | * Returns 0 on success. | ||
137 | * | ||
138 | **/ | ||
139 | int | ||
140 | gnutls_pkcs12_init (gnutls_pkcs12_t * pkcs12) | ||
141 | { | ||
142 | *pkcs12 = gnutls_calloc (1, sizeof (gnutls_pkcs12_int)); | ||
143 | |||
144 | if (*pkcs12) | ||
145 | { | ||
146 | int result = asn1_create_element (_gnutls_get_pkix (), | ||
147 | "PKIX1.pkcs-12-PFX", | ||
148 | &(*pkcs12)->pkcs12); | ||
149 | if (result != ASN1_SUCCESS) | ||
150 | { | ||
151 | gnutls_assert (); | ||
152 | gnutls_free (*pkcs12); | ||
153 | return _gnutls_asn2err (result); | ||
154 | } | ||
155 | return 0; /* success */ | ||
156 | } | ||
157 | return GNUTLS_E_MEMORY_ERROR; | ||
158 | } | ||
159 | |||
160 | /** | ||
161 | * gnutls_pkcs12_deinit - This function deinitializes memory used by a gnutls_pkcs12_t structure | ||
162 | * @pkcs12: The structure to be initialized | ||
163 | * | ||
164 | * This function will deinitialize a PKCS12 structure. | ||
165 | * | ||
166 | **/ | ||
167 | void | ||
168 | gnutls_pkcs12_deinit (gnutls_pkcs12_t pkcs12) | ||
169 | { | ||
170 | if (!pkcs12) | ||
171 | return; | ||
172 | |||
173 | if (pkcs12->pkcs12) | ||
174 | asn1_delete_structure (&pkcs12->pkcs12); | ||
175 | |||
176 | gnutls_free (pkcs12); | ||
177 | } | ||
178 | |||
179 | /** | ||
180 | * gnutls_pkcs12_import - This function will import a DER or PEM encoded PKCS12 structure | ||
181 | * @pkcs12: The structure to store the parsed PKCS12. | ||
182 | * @data: The DER or PEM encoded PKCS12. | ||
183 | * @format: One of DER or PEM | ||
184 | * @flags: an ORed sequence of gnutls_privkey_pkcs8_flags | ||
185 | * | ||
186 | * This function will convert the given DER or PEM encoded PKCS12 | ||
187 | * to the native gnutls_pkcs12_t format. The output will be stored in 'pkcs12'. | ||
188 | * | ||
189 | * If the PKCS12 is PEM encoded it should have a header of "PKCS12". | ||
190 | * | ||
191 | * Returns 0 on success. | ||
192 | * | ||
193 | **/ | ||
194 | int | ||
195 | gnutls_pkcs12_import (gnutls_pkcs12_t pkcs12, | ||
196 | const gnutls_datum_t * data, | ||
197 | gnutls_x509_crt_fmt_t format, unsigned int flags) | ||
198 | { | ||
199 | int result = 0, need_free = 0; | ||
200 | gnutls_datum_t _data; | ||
201 | |||
202 | _data.data = data->data; | ||
203 | _data.size = data->size; | ||
204 | |||
205 | if (pkcs12 == NULL) | ||
206 | { | ||
207 | gnutls_assert (); | ||
208 | return GNUTLS_E_INVALID_REQUEST; | ||
209 | } | ||
210 | |||
211 | /* If the PKCS12 is in PEM format then decode it | ||
212 | */ | ||
213 | if (format == GNUTLS_X509_FMT_PEM) | ||
214 | { | ||
215 | opaque *out; | ||
216 | |||
217 | result = _gnutls_fbase64_decode (PEM_PKCS12, data->data, data->size, | ||
218 | &out); | ||
219 | |||
220 | if (result <= 0) | ||
221 | { | ||
222 | if (result == 0) | ||
223 | result = GNUTLS_E_INTERNAL_ERROR; | ||
224 | gnutls_assert (); | ||
225 | return result; | ||
226 | } | ||
227 | |||
228 | _data.data = out; | ||
229 | _data.size = result; | ||
230 | |||
231 | need_free = 1; | ||
232 | } | ||
233 | |||
234 | result = asn1_der_decoding (&pkcs12->pkcs12, _data.data, _data.size, NULL); | ||
235 | if (result != ASN1_SUCCESS) | ||
236 | { | ||
237 | result = _gnutls_asn2err (result); | ||
238 | gnutls_assert (); | ||
239 | goto cleanup; | ||
240 | } | ||
241 | |||
242 | if (need_free) | ||
243 | _gnutls_free_datum (&_data); | ||
244 | |||
245 | return 0; | ||
246 | |||
247 | cleanup: | ||
248 | if (need_free) | ||
249 | _gnutls_free_datum (&_data); | ||
250 | return result; | ||
251 | } | ||
252 | |||
253 | |||
254 | /** | ||
255 | * gnutls_pkcs12_export - This function will export the pkcs12 structure | ||
256 | * @pkcs12: Holds the pkcs12 structure | ||
257 | * @format: the format of output params. One of PEM or DER. | ||
258 | * @output_data: will contain a structure PEM or DER encoded | ||
259 | * @output_data_size: holds the size of output_data (and will be | ||
260 | * replaced by the actual size of parameters) | ||
261 | * | ||
262 | * This function will export the pkcs12 structure to DER or PEM format. | ||
263 | * | ||
264 | * If the buffer provided is not long enough to hold the output, then | ||
265 | * *output_data_size will be updated and GNUTLS_E_SHORT_MEMORY_BUFFER | ||
266 | * will be returned. | ||
267 | * | ||
268 | * If the structure is PEM encoded, it will have a header | ||
269 | * of "BEGIN PKCS12". | ||
270 | * | ||
271 | * Return value: In case of failure a negative value will be | ||
272 | * returned, and 0 on success. | ||
273 | * | ||
274 | **/ | ||
275 | int | ||
276 | gnutls_pkcs12_export (gnutls_pkcs12_t pkcs12, | ||
277 | gnutls_x509_crt_fmt_t format, void *output_data, | ||
278 | size_t * output_data_size) | ||
279 | { | ||
280 | if (pkcs12 == NULL) | ||
281 | { | ||
282 | gnutls_assert (); | ||
283 | return GNUTLS_E_INVALID_REQUEST; | ||
284 | } | ||
285 | |||
286 | return _gnutls_x509_export_int (pkcs12->pkcs12, format, PEM_PKCS12, | ||
287 | output_data, output_data_size); | ||
288 | } | ||
289 | |||
290 | static int | ||
291 | oid2bag (const char *oid) | ||
292 | { | ||
293 | if (strcmp (oid, BAG_PKCS8_KEY) == 0) | ||
294 | return GNUTLS_BAG_PKCS8_KEY; | ||
295 | if (strcmp (oid, BAG_PKCS8_ENCRYPTED_KEY) == 0) | ||
296 | return GNUTLS_BAG_PKCS8_ENCRYPTED_KEY; | ||
297 | if (strcmp (oid, BAG_CERTIFICATE) == 0) | ||
298 | return GNUTLS_BAG_CERTIFICATE; | ||
299 | if (strcmp (oid, BAG_CRL) == 0) | ||
300 | return GNUTLS_BAG_CRL; | ||
301 | |||
302 | return GNUTLS_BAG_UNKNOWN; | ||
303 | } | ||
304 | |||
305 | static const char * | ||
306 | bag_to_oid (int bag) | ||
307 | { | ||
308 | switch (bag) | ||
309 | { | ||
310 | case GNUTLS_BAG_PKCS8_KEY: | ||
311 | return BAG_PKCS8_KEY; | ||
312 | case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY: | ||
313 | return BAG_PKCS8_ENCRYPTED_KEY; | ||
314 | case GNUTLS_BAG_CERTIFICATE: | ||
315 | return BAG_CERTIFICATE; | ||
316 | case GNUTLS_BAG_CRL: | ||
317 | return BAG_CRL; | ||
318 | } | ||
319 | return NULL; | ||
320 | } | ||
321 | |||
322 | static inline char * | ||
323 | ucs2_to_ascii (char *data, int size) | ||
324 | { | ||
325 | int i, j; | ||
326 | |||
327 | for (i = 0; i < size / 2; i++) | ||
328 | { | ||
329 | j = 2 * i + 1; | ||
330 | if (isascii (data[j])) | ||
331 | data[i] = data[i * 2 + 1]; | ||
332 | else | ||
333 | data[i] = '?'; | ||
334 | } | ||
335 | data[i] = 0; | ||
336 | |||
337 | return data; | ||
338 | } | ||
339 | |||
340 | /* Decodes the SafeContents, and puts the output in | ||
341 | * the given bag. | ||
342 | */ | ||
343 | int | ||
344 | _pkcs12_decode_safe_contents (const gnutls_datum_t * content, | ||
345 | gnutls_pkcs12_bag_t bag) | ||
346 | { | ||
347 | char oid[128], root[MAX_NAME_SIZE]; | ||
348 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
349 | int len, result; | ||
350 | int bag_type; | ||
351 | gnutls_datum_t attr_val; | ||
352 | int count = 0, i, attributes, j; | ||
353 | size_t size; | ||
354 | |||
355 | /* Step 1. Extract the SEQUENCE. | ||
356 | */ | ||
357 | |||
358 | if ((result = asn1_create_element | ||
359 | (_gnutls_get_pkix (), "PKIX1.pkcs-12-SafeContents", | ||
360 | &c2)) != ASN1_SUCCESS) | ||
361 | { | ||
362 | gnutls_assert (); | ||
363 | result = _gnutls_asn2err (result); | ||
364 | goto cleanup; | ||
365 | } | ||
366 | |||
367 | result = asn1_der_decoding (&c2, content->data, content->size, NULL); | ||
368 | if (result != ASN1_SUCCESS) | ||
369 | { | ||
370 | gnutls_assert (); | ||
371 | result = _gnutls_asn2err (result); | ||
372 | goto cleanup; | ||
373 | } | ||
374 | |||
375 | /* Count the number of bags | ||
376 | */ | ||
377 | result = asn1_number_of_elements (c2, "", &count); | ||
378 | if (result != ASN1_SUCCESS) | ||
379 | { | ||
380 | gnutls_assert (); | ||
381 | result = _gnutls_asn2err (result); | ||
382 | goto cleanup; | ||
383 | } | ||
384 | |||
385 | bag->bag_elements = MIN (MAX_BAG_ELEMENTS, count); | ||
386 | |||
387 | for (i = 0; i < bag->bag_elements; i++) | ||
388 | { | ||
389 | |||
390 | snprintf (root, sizeof (root), "?%u.bagId", i + 1); | ||
391 | |||
392 | len = sizeof (oid); | ||
393 | result = asn1_read_value (c2, root, oid, &len); | ||
394 | if (result != ASN1_SUCCESS) | ||
395 | { | ||
396 | gnutls_assert (); | ||
397 | result = _gnutls_asn2err (result); | ||
398 | goto cleanup; | ||
399 | } | ||
400 | |||
401 | /* Read the Bag type | ||
402 | */ | ||
403 | bag_type = oid2bag (oid); | ||
404 | |||
405 | if (bag_type < 0) | ||
406 | { | ||
407 | gnutls_assert (); | ||
408 | goto cleanup; | ||
409 | } | ||
410 | |||
411 | /* Read the Bag Value | ||
412 | */ | ||
413 | |||
414 | snprintf (root, sizeof (root), "?%u.bagValue", i + 1); | ||
415 | |||
416 | result = _gnutls_x509_read_value (c2, root, &bag->element[i].data, 0); | ||
417 | if (result < 0) | ||
418 | { | ||
419 | gnutls_assert (); | ||
420 | goto cleanup; | ||
421 | } | ||
422 | |||
423 | if (bag_type == GNUTLS_BAG_CERTIFICATE || bag_type == GNUTLS_BAG_CRL) | ||
424 | { | ||
425 | gnutls_datum_t tmp = bag->element[i].data; | ||
426 | |||
427 | result = | ||
428 | _pkcs12_decode_crt_bag (bag_type, &tmp, &bag->element[i].data); | ||
429 | if (result < 0) | ||
430 | { | ||
431 | gnutls_assert (); | ||
432 | goto cleanup; | ||
433 | } | ||
434 | |||
435 | _gnutls_free_datum (&tmp); | ||
436 | } | ||
437 | |||
438 | /* read the bag attributes | ||
439 | */ | ||
440 | snprintf (root, sizeof (root), "?%u.bagAttributes", i + 1); | ||
441 | |||
442 | result = asn1_number_of_elements (c2, root, &attributes); | ||
443 | if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND) | ||
444 | { | ||
445 | gnutls_assert (); | ||
446 | result = _gnutls_asn2err (result); | ||
447 | goto cleanup; | ||
448 | } | ||
449 | |||
450 | if (attributes < 0) | ||
451 | attributes = 1; | ||
452 | |||
453 | if (result != ASN1_ELEMENT_NOT_FOUND) | ||
454 | for (j = 0; j < attributes; j++) | ||
455 | { | ||
456 | |||
457 | snprintf (root, sizeof (root), "?%u.bagAttributes.?%u", i + 1, | ||
458 | j + 1); | ||
459 | |||
460 | result = | ||
461 | _gnutls_x509_decode_and_read_attribute (c2, root, oid, | ||
462 | sizeof (oid), &attr_val, | ||
463 | 1, 0); | ||
464 | |||
465 | if (result < 0) | ||
466 | { | ||
467 | gnutls_assert (); | ||
468 | continue; /* continue in case we find some known attributes */ | ||
469 | } | ||
470 | |||
471 | if (strcmp (oid, KEY_ID_OID) == 0) | ||
472 | { | ||
473 | size = attr_val.size; | ||
474 | |||
475 | result = | ||
476 | _gnutls_x509_decode_octet_string (NULL, attr_val.data, size, | ||
477 | attr_val.data, &size); | ||
478 | attr_val.size = size; | ||
479 | if (result < 0) | ||
480 | { | ||
481 | _gnutls_free_datum (&attr_val); | ||
482 | gnutls_assert (); | ||
483 | _gnutls_x509_log | ||
484 | ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid); | ||
485 | continue; | ||
486 | } | ||
487 | bag->element[i].local_key_id = attr_val; | ||
488 | } | ||
489 | else if (strcmp (oid, FRIENDLY_NAME_OID) == 0) | ||
490 | { | ||
491 | size = attr_val.size; | ||
492 | result = | ||
493 | _gnutls_x509_decode_octet_string ("BMPString", | ||
494 | attr_val.data, size, | ||
495 | attr_val.data, &size); | ||
496 | attr_val.size = size; | ||
497 | if (result < 0) | ||
498 | { | ||
499 | _gnutls_free_datum (&attr_val); | ||
500 | gnutls_assert (); | ||
501 | _gnutls_x509_log | ||
502 | ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid); | ||
503 | continue; | ||
504 | } | ||
505 | bag->element[i].friendly_name = | ||
506 | ucs2_to_ascii (attr_val.data, attr_val.size); | ||
507 | } | ||
508 | else | ||
509 | { | ||
510 | _gnutls_free_datum (&attr_val); | ||
511 | _gnutls_x509_log | ||
512 | ("Unknown PKCS12 Bag Attribute OID '%s'\n", oid); | ||
513 | } | ||
514 | } | ||
515 | |||
516 | |||
517 | bag->element[i].type = bag_type; | ||
518 | |||
519 | } | ||
520 | |||
521 | asn1_delete_structure (&c2); | ||
522 | |||
523 | |||
524 | return 0; | ||
525 | |||
526 | cleanup: | ||
527 | if (c2) | ||
528 | asn1_delete_structure (&c2); | ||
529 | return result; | ||
530 | |||
531 | } | ||
532 | |||
533 | |||
534 | static int | ||
535 | _parse_safe_contents (ASN1_TYPE sc, const char *sc_name, | ||
536 | gnutls_pkcs12_bag_t bag) | ||
537 | { | ||
538 | gnutls_datum_t content = { NULL, 0 }; | ||
539 | int result; | ||
540 | |||
541 | /* Step 1. Extract the content. | ||
542 | */ | ||
543 | |||
544 | result = _gnutls_x509_read_value (sc, sc_name, &content, 1); | ||
545 | if (result < 0) | ||
546 | { | ||
547 | gnutls_assert (); | ||
548 | goto cleanup; | ||
549 | } | ||
550 | |||
551 | result = _pkcs12_decode_safe_contents (&content, bag); | ||
552 | if (result < 0) | ||
553 | { | ||
554 | gnutls_assert (); | ||
555 | goto cleanup; | ||
556 | } | ||
557 | |||
558 | _gnutls_free_datum (&content); | ||
559 | |||
560 | return 0; | ||
561 | |||
562 | cleanup: | ||
563 | _gnutls_free_datum (&content); | ||
564 | return result; | ||
565 | } | ||
566 | |||
567 | |||
568 | /** | ||
569 | * gnutls_pkcs12_get_bag - This function returns a Bag from a PKCS12 structure | ||
570 | * @pkcs12: should contain a gnutls_pkcs12_t structure | ||
571 | * @indx: contains the index of the bag to extract | ||
572 | * @bag: An initialized bag, where the contents of the bag will be copied | ||
573 | * | ||
574 | * This function will return a Bag from the PKCS12 structure. | ||
575 | * Returns 0 on success. | ||
576 | * | ||
577 | * After the last Bag has been read GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE | ||
578 | * will be returned. | ||
579 | * | ||
580 | **/ | ||
581 | int | ||
582 | gnutls_pkcs12_get_bag (gnutls_pkcs12_t pkcs12, | ||
583 | int indx, gnutls_pkcs12_bag_t bag) | ||
584 | { | ||
585 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
586 | int result, len; | ||
587 | char root2[MAX_NAME_SIZE]; | ||
588 | char oid[128]; | ||
589 | |||
590 | if (pkcs12 == NULL) | ||
591 | { | ||
592 | gnutls_assert (); | ||
593 | return GNUTLS_E_INVALID_REQUEST; | ||
594 | } | ||
595 | |||
596 | /* Step 1. decode the data. | ||
597 | */ | ||
598 | result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, &c2, NULL); | ||
599 | if (result < 0) | ||
600 | { | ||
601 | gnutls_assert (); | ||
602 | return result; | ||
603 | } | ||
604 | |||
605 | /* Step 2. Parse the AuthenticatedSafe | ||
606 | */ | ||
607 | |||
608 | snprintf (root2, sizeof (root2), "?%u.contentType", indx + 1); | ||
609 | |||
610 | len = sizeof (oid) - 1; | ||
611 | result = asn1_read_value (c2, root2, oid, &len); | ||
612 | |||
613 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
614 | { | ||
615 | result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
616 | goto cleanup; | ||
617 | } | ||
618 | |||
619 | if (result != ASN1_SUCCESS) | ||
620 | { | ||
621 | gnutls_assert (); | ||
622 | result = _gnutls_asn2err (result); | ||
623 | goto cleanup; | ||
624 | } | ||
625 | |||
626 | /* Not encrypted Bag | ||
627 | */ | ||
628 | |||
629 | snprintf (root2, sizeof (root2), "?%u.content", indx + 1); | ||
630 | |||
631 | if (strcmp (oid, DATA_OID) == 0) | ||
632 | { | ||
633 | result = _parse_safe_contents (c2, root2, bag); | ||
634 | goto cleanup; | ||
635 | } | ||
636 | |||
637 | /* ENC_DATA_OID needs decryption */ | ||
638 | |||
639 | bag->element[0].type = GNUTLS_BAG_ENCRYPTED; | ||
640 | bag->bag_elements = 1; | ||
641 | |||
642 | result = _gnutls_x509_read_value (c2, root2, &bag->element[0].data, 0); | ||
643 | if (result < 0) | ||
644 | { | ||
645 | gnutls_assert (); | ||
646 | goto cleanup; | ||
647 | } | ||
648 | |||
649 | result = 0; | ||
650 | |||
651 | cleanup: | ||
652 | if (c2) | ||
653 | asn1_delete_structure (&c2); | ||
654 | return result; | ||
655 | } | ||
656 | |||
657 | /* Creates an empty PFX structure for the PKCS12 structure. | ||
658 | */ | ||
659 | static int | ||
660 | create_empty_pfx (ASN1_TYPE pkcs12) | ||
661 | { | ||
662 | uint8_t three = 3; | ||
663 | int result; | ||
664 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
665 | |||
666 | /* Use version 3 | ||
667 | */ | ||
668 | result = asn1_write_value (pkcs12, "version", &three, 1); | ||
669 | if (result != ASN1_SUCCESS) | ||
670 | { | ||
671 | gnutls_assert (); | ||
672 | result = _gnutls_asn2err (result); | ||
673 | goto cleanup; | ||
674 | } | ||
675 | |||
676 | /* Write the content type of the data | ||
677 | */ | ||
678 | result = asn1_write_value (pkcs12, "authSafe.contentType", DATA_OID, 1); | ||
679 | if (result != ASN1_SUCCESS) | ||
680 | { | ||
681 | gnutls_assert (); | ||
682 | result = _gnutls_asn2err (result); | ||
683 | goto cleanup; | ||
684 | } | ||
685 | |||
686 | /* Check if the authenticatedSafe content is empty, and encode a | ||
687 | * null one in that case. | ||
688 | */ | ||
689 | |||
690 | if ((result = asn1_create_element | ||
691 | (_gnutls_get_pkix (), "PKIX1.pkcs-12-AuthenticatedSafe", | ||
692 | &c2)) != ASN1_SUCCESS) | ||
693 | { | ||
694 | gnutls_assert (); | ||
695 | result = _gnutls_asn2err (result); | ||
696 | goto cleanup; | ||
697 | } | ||
698 | |||
699 | result = | ||
700 | _gnutls_x509_der_encode_and_copy (c2, "", pkcs12, "authSafe.content", 1); | ||
701 | if (result < 0) | ||
702 | { | ||
703 | gnutls_assert (); | ||
704 | goto cleanup; | ||
705 | } | ||
706 | asn1_delete_structure (&c2); | ||
707 | |||
708 | return 0; | ||
709 | |||
710 | cleanup: | ||
711 | asn1_delete_structure (&c2); | ||
712 | return result; | ||
713 | |||
714 | } | ||
715 | |||
716 | /** | ||
717 | * gnutls_pkcs12_set_bag - This function inserts a Bag into a PKCS12 structure | ||
718 | * @pkcs12: should contain a gnutls_pkcs12_t structure | ||
719 | * @bag: An initialized bag | ||
720 | * | ||
721 | * This function will insert a Bag into the PKCS12 structure. | ||
722 | * Returns 0 on success. | ||
723 | * | ||
724 | **/ | ||
725 | int | ||
726 | gnutls_pkcs12_set_bag (gnutls_pkcs12_t pkcs12, gnutls_pkcs12_bag_t bag) | ||
727 | { | ||
728 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
729 | ASN1_TYPE safe_cont = ASN1_TYPE_EMPTY; | ||
730 | int result; | ||
731 | int enc = 0, dum = 1; | ||
732 | char null; | ||
733 | |||
734 | if (pkcs12 == NULL) | ||
735 | { | ||
736 | gnutls_assert (); | ||
737 | return GNUTLS_E_INVALID_REQUEST; | ||
738 | } | ||
739 | |||
740 | /* Step 1. Check if the pkcs12 structure is empty. In that | ||
741 | * case generate an empty PFX. | ||
742 | */ | ||
743 | result = asn1_read_value (pkcs12->pkcs12, "authSafe.content", &null, &dum); | ||
744 | if (result == ASN1_VALUE_NOT_FOUND) | ||
745 | { | ||
746 | result = create_empty_pfx (pkcs12->pkcs12); | ||
747 | if (result < 0) | ||
748 | { | ||
749 | gnutls_assert (); | ||
750 | return result; | ||
751 | } | ||
752 | } | ||
753 | |||
754 | /* Step 2. decode the authenticatedSafe. | ||
755 | */ | ||
756 | result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, &c2, NULL); | ||
757 | if (result < 0) | ||
758 | { | ||
759 | gnutls_assert (); | ||
760 | return result; | ||
761 | } | ||
762 | |||
763 | /* Step 3. Encode the bag elements into a SafeContents | ||
764 | * structure. | ||
765 | */ | ||
766 | result = _pkcs12_encode_safe_contents (bag, &safe_cont, &enc); | ||
767 | if (result < 0) | ||
768 | { | ||
769 | gnutls_assert (); | ||
770 | return result; | ||
771 | } | ||
772 | |||
773 | /* Step 4. Insert the encoded SafeContents into the AuthenticatedSafe | ||
774 | * structure. | ||
775 | */ | ||
776 | result = asn1_write_value (c2, "", "NEW", 1); | ||
777 | if (result != ASN1_SUCCESS) | ||
778 | { | ||
779 | gnutls_assert (); | ||
780 | result = _gnutls_asn2err (result); | ||
781 | goto cleanup; | ||
782 | } | ||
783 | |||
784 | if (enc) | ||
785 | result = asn1_write_value (c2, "?LAST.contentType", ENC_DATA_OID, 1); | ||
786 | else | ||
787 | result = asn1_write_value (c2, "?LAST.contentType", DATA_OID, 1); | ||
788 | if (result != ASN1_SUCCESS) | ||
789 | { | ||
790 | gnutls_assert (); | ||
791 | result = _gnutls_asn2err (result); | ||
792 | goto cleanup; | ||
793 | } | ||
794 | |||
795 | if (enc) | ||
796 | { | ||
797 | /* Encrypted packets are written directly. | ||
798 | */ | ||
799 | result = | ||
800 | asn1_write_value (c2, "?LAST.content", | ||
801 | bag->element[0].data.data, | ||
802 | bag->element[0].data.size); | ||
803 | if (result != ASN1_SUCCESS) | ||
804 | { | ||
805 | gnutls_assert (); | ||
806 | result = _gnutls_asn2err (result); | ||
807 | goto cleanup; | ||
808 | } | ||
809 | } | ||
810 | else | ||
811 | { | ||
812 | result = | ||
813 | _gnutls_x509_der_encode_and_copy (safe_cont, "", c2, | ||
814 | "?LAST.content", 1); | ||
815 | if (result < 0) | ||
816 | { | ||
817 | gnutls_assert (); | ||
818 | goto cleanup; | ||
819 | } | ||
820 | } | ||
821 | |||
822 | asn1_delete_structure (&safe_cont); | ||
823 | |||
824 | |||
825 | /* Step 5. Reencode and copy the AuthenticatedSafe into the pkcs12 | ||
826 | * structure. | ||
827 | */ | ||
828 | result = | ||
829 | _gnutls_x509_der_encode_and_copy (c2, "", pkcs12->pkcs12, | ||
830 | "authSafe.content", 1); | ||
831 | if (result < 0) | ||
832 | { | ||
833 | gnutls_assert (); | ||
834 | goto cleanup; | ||
835 | } | ||
836 | |||
837 | asn1_delete_structure (&c2); | ||
838 | |||
839 | return 0; | ||
840 | |||
841 | cleanup: | ||
842 | asn1_delete_structure (&c2); | ||
843 | asn1_delete_structure (&safe_cont); | ||
844 | return result; | ||
845 | } | ||
846 | |||
847 | /** | ||
848 | * gnutls_pkcs12_generate_mac - This function generates the MAC of the PKCS12 structure | ||
849 | * @pkcs12: should contain a gnutls_pkcs12_t structure | ||
850 | * @pass: The password for the MAC | ||
851 | * | ||
852 | * This function will generate a MAC for the PKCS12 structure. | ||
853 | * Returns 0 on success. | ||
854 | * | ||
855 | **/ | ||
856 | int | ||
857 | gnutls_pkcs12_generate_mac (gnutls_pkcs12_t pkcs12, const char *pass) | ||
858 | { | ||
859 | opaque salt[8], key[20]; | ||
860 | int result; | ||
861 | const int iter = 1; | ||
862 | mac_hd_t td1 = NULL; | ||
863 | gnutls_datum_t tmp = { NULL, 0 }; | ||
864 | opaque sha_mac[20]; | ||
865 | |||
866 | if (pkcs12 == NULL) | ||
867 | { | ||
868 | gnutls_assert (); | ||
869 | return GNUTLS_E_INVALID_REQUEST; | ||
870 | } | ||
871 | |||
872 | /* Generate the salt. | ||
873 | */ | ||
874 | if (gc_nonce (salt, sizeof (salt)) != GC_OK) | ||
875 | { | ||
876 | gnutls_assert (); | ||
877 | return GNUTLS_E_RANDOM_FAILED; | ||
878 | } | ||
879 | |||
880 | /* Write the salt into the structure. | ||
881 | */ | ||
882 | result = | ||
883 | asn1_write_value (pkcs12->pkcs12, "macData.macSalt", salt, sizeof (salt)); | ||
884 | if (result != ASN1_SUCCESS) | ||
885 | { | ||
886 | gnutls_assert (); | ||
887 | result = _gnutls_asn2err (result); | ||
888 | goto cleanup; | ||
889 | } | ||
890 | |||
891 | /* write the iterations | ||
892 | */ | ||
893 | |||
894 | if (iter > 1) | ||
895 | { | ||
896 | result = | ||
897 | _gnutls_x509_write_uint32 (pkcs12->pkcs12, "macData.iterations", | ||
898 | iter); | ||
899 | if (result < 0) | ||
900 | { | ||
901 | gnutls_assert (); | ||
902 | goto cleanup; | ||
903 | } | ||
904 | } | ||
905 | |||
906 | /* Generate the key. | ||
907 | */ | ||
908 | result = _pkcs12_string_to_key (3 /*MAC*/, salt, sizeof (salt), | ||
909 | iter, pass, sizeof (key), key); | ||
910 | if (result < 0) | ||
911 | { | ||
912 | gnutls_assert (); | ||
913 | goto cleanup; | ||
914 | } | ||
915 | |||
916 | /* Get the data to be MACed | ||
917 | */ | ||
918 | result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, NULL, &tmp); | ||
919 | if (result < 0) | ||
920 | { | ||
921 | gnutls_assert (); | ||
922 | goto cleanup; | ||
923 | } | ||
924 | |||
925 | /* MAC the data | ||
926 | */ | ||
927 | td1 = _gnutls_hmac_init (GNUTLS_MAC_SHA1, key, sizeof (key)); | ||
928 | if (td1 == GNUTLS_MAC_FAILED) | ||
929 | { | ||
930 | gnutls_assert (); | ||
931 | result = GNUTLS_E_INTERNAL_ERROR; | ||
932 | goto cleanup; | ||
933 | } | ||
934 | |||
935 | _gnutls_hmac (td1, tmp.data, tmp.size); | ||
936 | _gnutls_free_datum (&tmp); | ||
937 | |||
938 | _gnutls_hmac_deinit (td1, sha_mac); | ||
939 | |||
940 | |||
941 | result = | ||
942 | asn1_write_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac, | ||
943 | sizeof (sha_mac)); | ||
944 | if (result != ASN1_SUCCESS) | ||
945 | { | ||
946 | gnutls_assert (); | ||
947 | result = _gnutls_asn2err (result); | ||
948 | goto cleanup; | ||
949 | } | ||
950 | |||
951 | result = | ||
952 | asn1_write_value (pkcs12->pkcs12, | ||
953 | "macData.mac.digestAlgorithm.parameters", NULL, 0); | ||
954 | if (result != ASN1_SUCCESS) | ||
955 | { | ||
956 | gnutls_assert (); | ||
957 | result = _gnutls_asn2err (result); | ||
958 | goto cleanup; | ||
959 | } | ||
960 | |||
961 | result = | ||
962 | asn1_write_value (pkcs12->pkcs12, | ||
963 | "macData.mac.digestAlgorithm.algorithm", HASH_OID_SHA1, | ||
964 | 1); | ||
965 | if (result != ASN1_SUCCESS) | ||
966 | { | ||
967 | gnutls_assert (); | ||
968 | result = _gnutls_asn2err (result); | ||
969 | goto cleanup; | ||
970 | } | ||
971 | |||
972 | return 0; | ||
973 | |||
974 | cleanup: | ||
975 | _gnutls_free_datum (&tmp); | ||
976 | return result; | ||
977 | } | ||
978 | |||
979 | /** | ||
980 | * gnutls_pkcs12_verify_mac - This function verifies the MAC of the PKCS12 structure | ||
981 | * @pkcs12: should contain a gnutls_pkcs12_t structure | ||
982 | * @pass: The password for the MAC | ||
983 | * | ||
984 | * This function will verify the MAC for the PKCS12 structure. | ||
985 | * Returns 0 on success. | ||
986 | * | ||
987 | **/ | ||
988 | int | ||
989 | gnutls_pkcs12_verify_mac (gnutls_pkcs12_t pkcs12, const char *pass) | ||
990 | { | ||
991 | opaque key[20]; | ||
992 | int result; | ||
993 | unsigned int iter; | ||
994 | int len; | ||
995 | mac_hd_t td1 = NULL; | ||
996 | gnutls_datum_t tmp = { NULL, 0 }, salt = | ||
997 | { | ||
998 | NULL, 0}; | ||
999 | opaque sha_mac[20]; | ||
1000 | opaque sha_mac_orig[20]; | ||
1001 | |||
1002 | if (pkcs12 == NULL) | ||
1003 | { | ||
1004 | gnutls_assert (); | ||
1005 | return GNUTLS_E_INVALID_REQUEST; | ||
1006 | } | ||
1007 | |||
1008 | /* read the iterations | ||
1009 | */ | ||
1010 | |||
1011 | result = | ||
1012 | _gnutls_x509_read_uint (pkcs12->pkcs12, "macData.iterations", &iter); | ||
1013 | if (result < 0) | ||
1014 | { | ||
1015 | iter = 1; /* the default */ | ||
1016 | } | ||
1017 | |||
1018 | |||
1019 | /* Read the salt from the structure. | ||
1020 | */ | ||
1021 | result = | ||
1022 | _gnutls_x509_read_value (pkcs12->pkcs12, "macData.macSalt", &salt, 0); | ||
1023 | if (result != ASN1_SUCCESS) | ||
1024 | { | ||
1025 | gnutls_assert (); | ||
1026 | result = _gnutls_asn2err (result); | ||
1027 | goto cleanup; | ||
1028 | } | ||
1029 | |||
1030 | /* Generate the key. | ||
1031 | */ | ||
1032 | result = _pkcs12_string_to_key (3 /*MAC*/, salt.data, salt.size, | ||
1033 | iter, pass, sizeof (key), key); | ||
1034 | if (result < 0) | ||
1035 | { | ||
1036 | gnutls_assert (); | ||
1037 | goto cleanup; | ||
1038 | } | ||
1039 | |||
1040 | _gnutls_free_datum (&salt); | ||
1041 | |||
1042 | /* Get the data to be MACed | ||
1043 | */ | ||
1044 | result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, NULL, &tmp); | ||
1045 | if (result < 0) | ||
1046 | { | ||
1047 | gnutls_assert (); | ||
1048 | goto cleanup; | ||
1049 | } | ||
1050 | |||
1051 | /* MAC the data | ||
1052 | */ | ||
1053 | td1 = _gnutls_hmac_init (GNUTLS_MAC_SHA1, key, sizeof (key)); | ||
1054 | if (td1 == GNUTLS_MAC_FAILED) | ||
1055 | { | ||
1056 | gnutls_assert (); | ||
1057 | result = GNUTLS_E_INTERNAL_ERROR; | ||
1058 | goto cleanup; | ||
1059 | } | ||
1060 | |||
1061 | _gnutls_hmac (td1, tmp.data, tmp.size); | ||
1062 | _gnutls_free_datum (&tmp); | ||
1063 | |||
1064 | _gnutls_hmac_deinit (td1, sha_mac); | ||
1065 | |||
1066 | len = sizeof (sha_mac_orig); | ||
1067 | result = | ||
1068 | asn1_read_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac_orig, | ||
1069 | &len); | ||
1070 | if (result != ASN1_SUCCESS) | ||
1071 | { | ||
1072 | gnutls_assert (); | ||
1073 | result = _gnutls_asn2err (result); | ||
1074 | goto cleanup; | ||
1075 | } | ||
1076 | |||
1077 | if (memcmp (sha_mac_orig, sha_mac, sizeof (sha_mac)) != 0) | ||
1078 | { | ||
1079 | gnutls_assert (); | ||
1080 | return GNUTLS_E_MAC_VERIFY_FAILED; | ||
1081 | } | ||
1082 | |||
1083 | return 0; | ||
1084 | |||
1085 | cleanup: | ||
1086 | _gnutls_free_datum (&tmp); | ||
1087 | _gnutls_free_datum (&salt); | ||
1088 | return result; | ||
1089 | } | ||
1090 | |||
1091 | |||
1092 | static int | ||
1093 | write_attributes (gnutls_pkcs12_bag_t bag, int elem, | ||
1094 | ASN1_TYPE c2, const char *where) | ||
1095 | { | ||
1096 | int result; | ||
1097 | char root[128]; | ||
1098 | |||
1099 | /* If the bag attributes are empty, then write | ||
1100 | * nothing to the attribute field. | ||
1101 | */ | ||
1102 | if (bag->element[elem].friendly_name == NULL && | ||
1103 | bag->element[elem].local_key_id.data == NULL) | ||
1104 | { | ||
1105 | /* no attributes | ||
1106 | */ | ||
1107 | result = asn1_write_value (c2, where, NULL, 0); | ||
1108 | if (result != ASN1_SUCCESS) | ||
1109 | { | ||
1110 | gnutls_assert (); | ||
1111 | return _gnutls_asn2err (result); | ||
1112 | } | ||
1113 | |||
1114 | return 0; | ||
1115 | } | ||
1116 | |||
1117 | if (bag->element[elem].local_key_id.data != NULL) | ||
1118 | { | ||
1119 | |||
1120 | /* Add a new Attribute | ||
1121 | */ | ||
1122 | result = asn1_write_value (c2, where, "NEW", 1); | ||
1123 | if (result != ASN1_SUCCESS) | ||
1124 | { | ||
1125 | gnutls_assert (); | ||
1126 | return _gnutls_asn2err (result); | ||
1127 | } | ||
1128 | |||
1129 | _gnutls_str_cpy (root, sizeof (root), where); | ||
1130 | _gnutls_str_cat (root, sizeof (root), ".?LAST"); | ||
1131 | |||
1132 | result = | ||
1133 | _gnutls_x509_encode_and_write_attribute (KEY_ID_OID, c2, root, | ||
1134 | bag->element[elem]. | ||
1135 | local_key_id.data, | ||
1136 | bag->element[elem]. | ||
1137 | local_key_id.size, 1); | ||
1138 | if (result < 0) | ||
1139 | { | ||
1140 | gnutls_assert (); | ||
1141 | return result; | ||
1142 | } | ||
1143 | } | ||
1144 | |||
1145 | if (bag->element[elem].friendly_name != NULL) | ||
1146 | { | ||
1147 | opaque *name; | ||
1148 | int size, i; | ||
1149 | const char *p; | ||
1150 | |||
1151 | /* Add a new Attribute | ||
1152 | */ | ||
1153 | result = asn1_write_value (c2, where, "NEW", 1); | ||
1154 | if (result != ASN1_SUCCESS) | ||
1155 | { | ||
1156 | gnutls_assert (); | ||
1157 | return _gnutls_asn2err (result); | ||
1158 | } | ||
1159 | |||
1160 | /* convert name to BMPString | ||
1161 | */ | ||
1162 | size = strlen (bag->element[elem].friendly_name) * 2; | ||
1163 | name = gnutls_malloc (size); | ||
1164 | |||
1165 | if (name == NULL) | ||
1166 | { | ||
1167 | gnutls_assert (); | ||
1168 | return GNUTLS_E_MEMORY_ERROR; | ||
1169 | } | ||
1170 | |||
1171 | p = bag->element[elem].friendly_name; | ||
1172 | for (i = 0; i < size; i += 2) | ||
1173 | { | ||
1174 | name[i] = 0; | ||
1175 | name[i + 1] = *p; | ||
1176 | p++; | ||
1177 | } | ||
1178 | |||
1179 | _gnutls_str_cpy (root, sizeof (root), where); | ||
1180 | _gnutls_str_cat (root, sizeof (root), ".?LAST"); | ||
1181 | |||
1182 | result = | ||
1183 | _gnutls_x509_encode_and_write_attribute (FRIENDLY_NAME_OID, c2, | ||
1184 | root, name, size, 1); | ||
1185 | |||
1186 | gnutls_free (name); | ||
1187 | |||
1188 | if (result < 0) | ||
1189 | { | ||
1190 | gnutls_assert (); | ||
1191 | return result; | ||
1192 | } | ||
1193 | } | ||
1194 | |||
1195 | return 0; | ||
1196 | } | ||
1197 | |||
1198 | |||
1199 | /* Encodes the bag into a SafeContents structure, and puts the output in | ||
1200 | * the given datum. Enc is set to non zero if the data are encrypted; | ||
1201 | */ | ||
1202 | int | ||
1203 | _pkcs12_encode_safe_contents (gnutls_pkcs12_bag_t bag, ASN1_TYPE * contents, | ||
1204 | int *enc) | ||
1205 | { | ||
1206 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
1207 | int result; | ||
1208 | int i; | ||
1209 | const char *oid; | ||
1210 | |||
1211 | if (bag->element[0].type == GNUTLS_BAG_ENCRYPTED && enc) | ||
1212 | { | ||
1213 | *enc = 1; | ||
1214 | return 0; /* ENCRYPTED BAG, do nothing. */ | ||
1215 | } | ||
1216 | else if (enc) | ||
1217 | *enc = 0; | ||
1218 | |||
1219 | /* Step 1. Create the SEQUENCE. | ||
1220 | */ | ||
1221 | |||
1222 | if ((result = asn1_create_element | ||
1223 | (_gnutls_get_pkix (), "PKIX1.pkcs-12-SafeContents", | ||
1224 | &c2)) != ASN1_SUCCESS) | ||
1225 | { | ||
1226 | gnutls_assert (); | ||
1227 | result = _gnutls_asn2err (result); | ||
1228 | goto cleanup; | ||
1229 | } | ||
1230 | |||
1231 | for (i = 0; i < bag->bag_elements; i++) | ||
1232 | { | ||
1233 | |||
1234 | oid = bag_to_oid (bag->element[i].type); | ||
1235 | if (oid == NULL) | ||
1236 | { | ||
1237 | gnutls_assert (); | ||
1238 | continue; | ||
1239 | } | ||
1240 | |||
1241 | result = asn1_write_value (c2, "", "NEW", 1); | ||
1242 | if (result != ASN1_SUCCESS) | ||
1243 | { | ||
1244 | gnutls_assert (); | ||
1245 | result = _gnutls_asn2err (result); | ||
1246 | goto cleanup; | ||
1247 | } | ||
1248 | |||
1249 | /* Copy the bag type. | ||
1250 | */ | ||
1251 | result = asn1_write_value (c2, "?LAST.bagId", oid, 1); | ||
1252 | if (result != ASN1_SUCCESS) | ||
1253 | { | ||
1254 | gnutls_assert (); | ||
1255 | result = _gnutls_asn2err (result); | ||
1256 | goto cleanup; | ||
1257 | } | ||
1258 | |||
1259 | /* Set empty attributes | ||
1260 | */ | ||
1261 | result = write_attributes (bag, i, c2, "?LAST.bagAttributes"); | ||
1262 | if (result < 0) | ||
1263 | { | ||
1264 | gnutls_assert (); | ||
1265 | goto cleanup; | ||
1266 | } | ||
1267 | |||
1268 | |||
1269 | /* Copy the Bag Value | ||
1270 | */ | ||
1271 | |||
1272 | if (bag->element[i].type == GNUTLS_BAG_CERTIFICATE || | ||
1273 | bag->element[i].type == GNUTLS_BAG_CRL) | ||
1274 | { | ||
1275 | gnutls_datum_t tmp; | ||
1276 | |||
1277 | /* in that case encode it to a CertBag or | ||
1278 | * a CrlBag. | ||
1279 | */ | ||
1280 | |||
1281 | result = | ||
1282 | _pkcs12_encode_crt_bag (bag->element[i].type, | ||
1283 | &bag->element[i].data, &tmp); | ||
1284 | |||
1285 | if (result < 0) | ||
1286 | { | ||
1287 | gnutls_assert (); | ||
1288 | goto cleanup; | ||
1289 | } | ||
1290 | |||
1291 | result = _gnutls_x509_write_value (c2, "?LAST.bagValue", &tmp, 0); | ||
1292 | |||
1293 | _gnutls_free_datum (&tmp); | ||
1294 | |||
1295 | } | ||
1296 | else | ||
1297 | { | ||
1298 | |||
1299 | result = _gnutls_x509_write_value (c2, "?LAST.bagValue", | ||
1300 | &bag->element[i].data, 0); | ||
1301 | } | ||
1302 | |||
1303 | if (result < 0) | ||
1304 | { | ||
1305 | gnutls_assert (); | ||
1306 | goto cleanup; | ||
1307 | } | ||
1308 | |||
1309 | } | ||
1310 | |||
1311 | /* Encode the data and copy them into the datum | ||
1312 | */ | ||
1313 | *contents = c2; | ||
1314 | |||
1315 | return 0; | ||
1316 | |||
1317 | cleanup: | ||
1318 | if (c2) | ||
1319 | asn1_delete_structure (&c2); | ||
1320 | return result; | ||
1321 | |||
1322 | } | ||
1323 | |||
1324 | |||
1325 | #endif /* ENABLE_PKI */ | ||
diff --git a/src/daemon/https/x509/pkcs12.h b/src/daemon/https/x509/pkcs12.h new file mode 100644 index 00000000..566058fb --- /dev/null +++ b/src/daemon/https/x509/pkcs12.h | |||
@@ -0,0 +1,208 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | // TODO clean | ||
26 | |||
27 | #ifndef GNUTLS_PKCS12_H | ||
28 | # define GNUTLS_PKCS12_H | ||
29 | |||
30 | #ifdef __cplusplus | ||
31 | extern "C" | ||
32 | { | ||
33 | #endif | ||
34 | |||
35 | #include <x509.h> | ||
36 | |||
37 | #define MAX_BAG_ELEMENTS 32 | ||
38 | |||
39 | /* PKCS12 structures handling | ||
40 | */ | ||
41 | struct gnutls_pkcs12_int; | ||
42 | |||
43 | struct gnutls_pkcs12_bag_int; | ||
44 | typedef struct gnutls_pkcs12_int | ||
45 | { | ||
46 | ASN1_TYPE pkcs12; | ||
47 | } gnutls_pkcs12_int; | ||
48 | |||
49 | typedef enum gnutls_pkcs12_bag_type_t | ||
50 | { | ||
51 | GNUTLS_BAG_EMPTY = 0, | ||
52 | |||
53 | GNUTLS_BAG_PKCS8_ENCRYPTED_KEY = 1, | ||
54 | GNUTLS_BAG_PKCS8_KEY, | ||
55 | GNUTLS_BAG_CERTIFICATE, | ||
56 | GNUTLS_BAG_CRL, | ||
57 | GNUTLS_BAG_ENCRYPTED = 10, | ||
58 | GNUTLS_BAG_UNKNOWN = 20 | ||
59 | } gnutls_pkcs12_bag_type_t; | ||
60 | |||
61 | struct bag_element | ||
62 | { | ||
63 | gnutls_datum_t data; | ||
64 | gnutls_pkcs12_bag_type_t type; | ||
65 | gnutls_datum_t local_key_id; | ||
66 | char *friendly_name; | ||
67 | }; | ||
68 | |||
69 | typedef struct gnutls_pkcs12_bag_int | ||
70 | { | ||
71 | struct bag_element element[MAX_BAG_ELEMENTS]; | ||
72 | int bag_elements; | ||
73 | } gnutls_pkcs12_bag_int; | ||
74 | |||
75 | /* Bag attributes */ | ||
76 | #define FRIENDLY_NAME_OID "1.2.840.113549.1.9.20" | ||
77 | #define KEY_ID_OID "1.2.840.113549.1.9.21" | ||
78 | |||
79 | typedef struct gnutls_pkcs12_int *gnutls_pkcs12_t; | ||
80 | typedef struct gnutls_pkcs12_bag_int *gnutls_pkcs12_bag_t; | ||
81 | |||
82 | int gnutls_pkcs12_init(gnutls_pkcs12_t * pkcs12); | ||
83 | void gnutls_pkcs12_deinit(gnutls_pkcs12_t pkcs12); | ||
84 | int gnutls_pkcs12_import(gnutls_pkcs12_t pkcs12, | ||
85 | const gnutls_datum_t * data, | ||
86 | gnutls_x509_crt_fmt_t format, | ||
87 | unsigned int flags); | ||
88 | int gnutls_pkcs12_export(gnutls_pkcs12_t pkcs12, | ||
89 | gnutls_x509_crt_fmt_t format, | ||
90 | void *output_data, | ||
91 | size_t * output_data_size); | ||
92 | |||
93 | int gnutls_pkcs12_get_bag(gnutls_pkcs12_t pkcs12, | ||
94 | int indx, | ||
95 | gnutls_pkcs12_bag_t bag); | ||
96 | int gnutls_pkcs12_set_bag(gnutls_pkcs12_t pkcs12, | ||
97 | gnutls_pkcs12_bag_t bag); | ||
98 | |||
99 | int gnutls_pkcs12_generate_mac(gnutls_pkcs12_t pkcs12, | ||
100 | const char *pass); | ||
101 | int gnutls_pkcs12_verify_mac(gnutls_pkcs12_t pkcs12, | ||
102 | const char *pass); | ||
103 | |||
104 | int gnutls_pkcs12_bag_decrypt(gnutls_pkcs12_bag_t bag, | ||
105 | const char *pass); | ||
106 | int gnutls_pkcs12_bag_encrypt(gnutls_pkcs12_bag_t bag, | ||
107 | const char *pass, | ||
108 | unsigned int flags); | ||
109 | |||
110 | gnutls_pkcs12_bag_type_t gnutls_pkcs12_bag_get_type(gnutls_pkcs12_bag_t | ||
111 | bag, | ||
112 | int indx); | ||
113 | int gnutls_pkcs12_bag_get_data(gnutls_pkcs12_bag_t bag, | ||
114 | int indx, | ||
115 | gnutls_datum_t * data); | ||
116 | int gnutls_pkcs12_bag_set_data(gnutls_pkcs12_bag_t bag, | ||
117 | gnutls_pkcs12_bag_type_t type, | ||
118 | const gnutls_datum_t * data); | ||
119 | int gnutls_pkcs12_bag_set_crl(gnutls_pkcs12_bag_t bag, | ||
120 | gnutls_x509_crl_t crl); | ||
121 | int gnutls_pkcs12_bag_set_crt(gnutls_pkcs12_bag_t bag, | ||
122 | gnutls_x509_crt_t crt); | ||
123 | |||
124 | int gnutls_pkcs12_bag_init(gnutls_pkcs12_bag_t * bag); | ||
125 | void gnutls_pkcs12_bag_deinit(gnutls_pkcs12_bag_t bag); | ||
126 | int gnutls_pkcs12_bag_get_count(gnutls_pkcs12_bag_t bag); | ||
127 | |||
128 | int gnutls_pkcs12_bag_get_key_id(gnutls_pkcs12_bag_t bag, | ||
129 | int indx, | ||
130 | gnutls_datum_t * id); | ||
131 | int gnutls_pkcs12_bag_set_key_id(gnutls_pkcs12_bag_t bag, | ||
132 | int indx, | ||
133 | const gnutls_datum_t * id); | ||
134 | |||
135 | int gnutls_pkcs12_bag_get_friendly_name(gnutls_pkcs12_bag_t bag, | ||
136 | int indx, | ||
137 | char **name); | ||
138 | int gnutls_pkcs12_bag_set_friendly_name(gnutls_pkcs12_bag_t bag, | ||
139 | int indx, | ||
140 | const char *name); | ||
141 | |||
142 | #ifdef __cplusplus | ||
143 | } | ||
144 | #endif | ||
145 | |||
146 | #define BAG_PKCS8_KEY "1.2.840.113549.1.12.10.1.1" | ||
147 | #define BAG_PKCS8_ENCRYPTED_KEY "1.2.840.113549.1.12.10.1.2" | ||
148 | #define BAG_CERTIFICATE "1.2.840.113549.1.12.10.1.3" | ||
149 | #define BAG_CRL "1.2.840.113549.1.12.10.1.4" | ||
150 | |||
151 | /* PKCS #7 | ||
152 | */ | ||
153 | #define DATA_OID "1.2.840.113549.1.7.1" | ||
154 | #define ENC_DATA_OID "1.2.840.113549.1.7.6" | ||
155 | |||
156 | int gnutls_pkcs12_init(gnutls_pkcs12_t * pkcs12); | ||
157 | void gnutls_pkcs12_deinit(gnutls_pkcs12_t pkcs12); | ||
158 | int gnutls_pkcs12_import(gnutls_pkcs12_t pkcs12, | ||
159 | const gnutls_datum_t * data, | ||
160 | gnutls_x509_crt_fmt_t format, | ||
161 | unsigned int flags); | ||
162 | |||
163 | int gnutls_pkcs12_get_bag(gnutls_pkcs12_t pkcs12, | ||
164 | int indx, | ||
165 | gnutls_pkcs12_bag_t bag); | ||
166 | |||
167 | int gnutls_pkcs12_bag_init(gnutls_pkcs12_bag_t * bag); | ||
168 | void gnutls_pkcs12_bag_deinit(gnutls_pkcs12_bag_t bag); | ||
169 | |||
170 | int _pkcs12_string_to_key(unsigned int id, | ||
171 | const opaque * salt, | ||
172 | unsigned int salt_size, | ||
173 | unsigned int iter, | ||
174 | const char *pw, | ||
175 | unsigned int req_keylen, | ||
176 | opaque * keybuf); | ||
177 | |||
178 | int _gnutls_pkcs7_decrypt_data(const gnutls_datum_t * data, | ||
179 | const char *password, | ||
180 | gnutls_datum_t * dec); | ||
181 | |||
182 | typedef enum schema_id | ||
183 | { | ||
184 | PBES2, /* the stuff in PKCS #5 */ | ||
185 | PKCS12_3DES_SHA1, /* the fucking stuff in PKCS #12 */ | ||
186 | PKCS12_ARCFOUR_SHA1, | ||
187 | PKCS12_RC2_40_SHA1 | ||
188 | } schema_id; | ||
189 | |||
190 | int _gnutls_pkcs7_encrypt_data(schema_id schema, | ||
191 | const gnutls_datum_t * data, | ||
192 | const char *password, | ||
193 | gnutls_datum_t * enc); | ||
194 | int _pkcs12_decode_safe_contents(const gnutls_datum_t * content, | ||
195 | gnutls_pkcs12_bag_t bag); | ||
196 | |||
197 | int _pkcs12_encode_safe_contents(gnutls_pkcs12_bag_t bag, | ||
198 | ASN1_TYPE * content, | ||
199 | int *enc); | ||
200 | |||
201 | int _pkcs12_decode_crt_bag(gnutls_pkcs12_bag_type_t type, | ||
202 | const gnutls_datum_t * in, | ||
203 | gnutls_datum_t * out); | ||
204 | int _pkcs12_encode_crt_bag(gnutls_pkcs12_bag_type_t type, | ||
205 | const gnutls_datum_t * raw, | ||
206 | gnutls_datum_t * out); | ||
207 | |||
208 | #endif /* GNUTLS_PKCS12_H */ | ||
diff --git a/src/daemon/https/x509/pkcs12_bag.c b/src/daemon/https/x509/pkcs12_bag.c new file mode 100644 index 00000000..c34ec757 --- /dev/null +++ b/src/daemon/https/x509/pkcs12_bag.c | |||
@@ -0,0 +1,770 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | /* Functions that relate on PKCS12 Bag packet parsing. | ||
26 | */ | ||
27 | |||
28 | #include <gnutls_int.h> | ||
29 | |||
30 | #ifdef ENABLE_PKI | ||
31 | |||
32 | #include <gnutls_datum.h> | ||
33 | #include <gnutls_global.h> | ||
34 | #include <gnutls_errors.h> | ||
35 | #include <common.h> | ||
36 | #include <pkcs12.h> | ||
37 | #include <privkey.h> | ||
38 | |||
39 | /** | ||
40 | * gnutls_pkcs12_bag_init - This function initializes a gnutls_pkcs12_bag_t structure | ||
41 | * @bag: The structure to be initialized | ||
42 | * | ||
43 | * This function will initialize a PKCS12 bag structure. PKCS12 Bags | ||
44 | * usually contain private keys, lists of X.509 Certificates and X.509 Certificate | ||
45 | * revocation lists. | ||
46 | * | ||
47 | * Returns 0 on success. | ||
48 | * | ||
49 | **/ | ||
50 | int | ||
51 | gnutls_pkcs12_bag_init (gnutls_pkcs12_bag_t * bag) | ||
52 | { | ||
53 | *bag = gnutls_calloc (1, sizeof (gnutls_pkcs12_bag_int)); | ||
54 | |||
55 | if (*bag) | ||
56 | { | ||
57 | return 0; /* success */ | ||
58 | } | ||
59 | return GNUTLS_E_MEMORY_ERROR; | ||
60 | } | ||
61 | |||
62 | static inline void | ||
63 | _pkcs12_bag_free_data (gnutls_pkcs12_bag_t bag) | ||
64 | { | ||
65 | int i; | ||
66 | |||
67 | for (i = 0; i < bag->bag_elements; i++) | ||
68 | { | ||
69 | _gnutls_free_datum (&bag->element[i].data); | ||
70 | _gnutls_free_datum (&bag->element[i].local_key_id); | ||
71 | gnutls_free (bag->element[i].friendly_name); | ||
72 | bag->element[i].friendly_name = NULL; | ||
73 | bag->element[i].type = 0; | ||
74 | } | ||
75 | |||
76 | } | ||
77 | |||
78 | |||
79 | /** | ||
80 | * gnutls_pkcs12_bag_deinit - This function deinitializes memory used by a gnutls_pkcs12_t structure | ||
81 | * @bag: The structure to be initialized | ||
82 | * | ||
83 | * This function will deinitialize a PKCS12 Bag structure. | ||
84 | * | ||
85 | **/ | ||
86 | void | ||
87 | gnutls_pkcs12_bag_deinit (gnutls_pkcs12_bag_t bag) | ||
88 | { | ||
89 | if (!bag) | ||
90 | return; | ||
91 | |||
92 | _pkcs12_bag_free_data (bag); | ||
93 | |||
94 | gnutls_free (bag); | ||
95 | } | ||
96 | |||
97 | /** | ||
98 | * gnutls_pkcs12_bag_get_type - This function returns the bag's type | ||
99 | * @bag: The bag | ||
100 | * @indx: The element of the bag to get the type | ||
101 | * | ||
102 | * This function will return the bag's type. One of the gnutls_pkcs12_bag_type_t | ||
103 | * enumerations. | ||
104 | * | ||
105 | **/ | ||
106 | gnutls_pkcs12_bag_type_t | ||
107 | gnutls_pkcs12_bag_get_type (gnutls_pkcs12_bag_t bag, int indx) | ||
108 | { | ||
109 | if (bag == NULL) | ||
110 | { | ||
111 | gnutls_assert (); | ||
112 | return GNUTLS_E_INVALID_REQUEST; | ||
113 | } | ||
114 | |||
115 | if (indx >= bag->bag_elements) | ||
116 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
117 | return bag->element[indx].type; | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * gnutls_pkcs12_bag_get_count - This function returns the bag's elements count | ||
122 | * @bag: The bag | ||
123 | * | ||
124 | * This function will return the number of the elements withing the bag. | ||
125 | * | ||
126 | **/ | ||
127 | int | ||
128 | gnutls_pkcs12_bag_get_count (gnutls_pkcs12_bag_t bag) | ||
129 | { | ||
130 | if (bag == NULL) | ||
131 | { | ||
132 | gnutls_assert (); | ||
133 | return GNUTLS_E_INVALID_REQUEST; | ||
134 | } | ||
135 | |||
136 | return bag->bag_elements; | ||
137 | } | ||
138 | |||
139 | /** | ||
140 | * gnutls_pkcs12_bag_get_data - This function returns the bag's data | ||
141 | * @bag: The bag | ||
142 | * @indx: The element of the bag to get the data from | ||
143 | * @data: where the bag's data will be. Should be treated as constant. | ||
144 | * | ||
145 | * This function will return the bag's data. The data is a constant | ||
146 | * that is stored into the bag. Should not be accessed after the bag | ||
147 | * is deleted. | ||
148 | * | ||
149 | * Returns 0 on success and a negative error code on error. | ||
150 | * | ||
151 | **/ | ||
152 | int | ||
153 | gnutls_pkcs12_bag_get_data (gnutls_pkcs12_bag_t bag, int indx, | ||
154 | gnutls_datum_t * data) | ||
155 | { | ||
156 | if (bag == NULL) | ||
157 | { | ||
158 | gnutls_assert (); | ||
159 | return GNUTLS_E_INVALID_REQUEST; | ||
160 | } | ||
161 | |||
162 | if (indx >= bag->bag_elements) | ||
163 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
164 | |||
165 | data->data = bag->element[indx].data.data; | ||
166 | data->size = bag->element[indx].data.size; | ||
167 | |||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | #define X509_CERT_OID "1.2.840.113549.1.9.22.1" | ||
172 | #define X509_CRL_OID "1.2.840.113549.1.9.23.1" | ||
173 | |||
174 | int | ||
175 | _pkcs12_decode_crt_bag (gnutls_pkcs12_bag_type_t type, | ||
176 | const gnutls_datum_t * in, gnutls_datum_t * out) | ||
177 | { | ||
178 | int ret; | ||
179 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
180 | |||
181 | if (type == GNUTLS_BAG_CERTIFICATE) | ||
182 | { | ||
183 | if ((ret = asn1_create_element (_gnutls_get_pkix (), | ||
184 | "PKIX1.pkcs-12-CertBag", | ||
185 | &c2)) != ASN1_SUCCESS) | ||
186 | { | ||
187 | gnutls_assert (); | ||
188 | ret = _gnutls_asn2err (ret); | ||
189 | goto cleanup; | ||
190 | } | ||
191 | |||
192 | ret = asn1_der_decoding (&c2, in->data, in->size, NULL); | ||
193 | if (ret != ASN1_SUCCESS) | ||
194 | { | ||
195 | gnutls_assert (); | ||
196 | ret = _gnutls_asn2err (ret); | ||
197 | goto cleanup; | ||
198 | } | ||
199 | |||
200 | ret = _gnutls_x509_read_value (c2, "certValue", out, 1); | ||
201 | if (ret < 0) | ||
202 | { | ||
203 | gnutls_assert (); | ||
204 | goto cleanup; | ||
205 | } | ||
206 | |||
207 | } | ||
208 | else | ||
209 | { /* CRL */ | ||
210 | if ((ret = asn1_create_element (_gnutls_get_pkix (), | ||
211 | "PKIX1.pkcs-12-CRLBag", | ||
212 | &c2)) != ASN1_SUCCESS) | ||
213 | { | ||
214 | gnutls_assert (); | ||
215 | ret = _gnutls_asn2err (ret); | ||
216 | goto cleanup; | ||
217 | } | ||
218 | |||
219 | ret = asn1_der_decoding (&c2, in->data, in->size, NULL); | ||
220 | if (ret != ASN1_SUCCESS) | ||
221 | { | ||
222 | gnutls_assert (); | ||
223 | ret = _gnutls_asn2err (ret); | ||
224 | goto cleanup; | ||
225 | } | ||
226 | |||
227 | ret = _gnutls_x509_read_value (c2, "crlValue", out, 1); | ||
228 | if (ret < 0) | ||
229 | { | ||
230 | gnutls_assert (); | ||
231 | goto cleanup; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | asn1_delete_structure (&c2); | ||
236 | |||
237 | return 0; | ||
238 | |||
239 | |||
240 | cleanup: | ||
241 | |||
242 | asn1_delete_structure (&c2); | ||
243 | return ret; | ||
244 | } | ||
245 | |||
246 | |||
247 | int | ||
248 | _pkcs12_encode_crt_bag (gnutls_pkcs12_bag_type_t type, | ||
249 | const gnutls_datum_t * raw, gnutls_datum_t * out) | ||
250 | { | ||
251 | int ret; | ||
252 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
253 | |||
254 | if (type == GNUTLS_BAG_CERTIFICATE) | ||
255 | { | ||
256 | if ((ret = asn1_create_element (_gnutls_get_pkix (), | ||
257 | "PKIX1.pkcs-12-CertBag", | ||
258 | &c2)) != ASN1_SUCCESS) | ||
259 | { | ||
260 | gnutls_assert (); | ||
261 | ret = _gnutls_asn2err (ret); | ||
262 | goto cleanup; | ||
263 | } | ||
264 | |||
265 | ret = asn1_write_value (c2, "certId", X509_CERT_OID, 1); | ||
266 | if (ret != ASN1_SUCCESS) | ||
267 | { | ||
268 | gnutls_assert (); | ||
269 | ret = _gnutls_asn2err (ret); | ||
270 | goto cleanup; | ||
271 | } | ||
272 | |||
273 | ret = _gnutls_x509_write_value (c2, "certValue", raw, 1); | ||
274 | if (ret < 0) | ||
275 | { | ||
276 | gnutls_assert (); | ||
277 | goto cleanup; | ||
278 | } | ||
279 | |||
280 | } | ||
281 | else | ||
282 | { /* CRL */ | ||
283 | if ((ret = asn1_create_element (_gnutls_get_pkix (), | ||
284 | "PKIX1.pkcs-12-CRLBag", | ||
285 | &c2)) != ASN1_SUCCESS) | ||
286 | { | ||
287 | gnutls_assert (); | ||
288 | ret = _gnutls_asn2err (ret); | ||
289 | goto cleanup; | ||
290 | } | ||
291 | |||
292 | ret = asn1_write_value (c2, "crlId", X509_CRL_OID, 1); | ||
293 | if (ret != ASN1_SUCCESS) | ||
294 | { | ||
295 | gnutls_assert (); | ||
296 | ret = _gnutls_asn2err (ret); | ||
297 | goto cleanup; | ||
298 | } | ||
299 | |||
300 | ret = _gnutls_x509_write_value (c2, "crlValue", raw, 1); | ||
301 | if (ret < 0) | ||
302 | { | ||
303 | gnutls_assert (); | ||
304 | goto cleanup; | ||
305 | } | ||
306 | } | ||
307 | |||
308 | ret = _gnutls_x509_der_encode (c2, "", out, 0); | ||
309 | |||
310 | if (ret < 0) | ||
311 | { | ||
312 | gnutls_assert (); | ||
313 | goto cleanup; | ||
314 | } | ||
315 | |||
316 | asn1_delete_structure (&c2); | ||
317 | |||
318 | return 0; | ||
319 | |||
320 | |||
321 | cleanup: | ||
322 | |||
323 | asn1_delete_structure (&c2); | ||
324 | return ret; | ||
325 | } | ||
326 | |||
327 | |||
328 | /** | ||
329 | * gnutls_pkcs12_bag_set_data - This function inserts data into the bag | ||
330 | * @bag: The bag | ||
331 | * @type: The data's type | ||
332 | * @data: the data to be copied. | ||
333 | * | ||
334 | * This function will insert the given data of the given type into the | ||
335 | * bag. | ||
336 | * | ||
337 | * Returns the index of the added bag on success, or a negative | ||
338 | * value on error. | ||
339 | * | ||
340 | **/ | ||
341 | int | ||
342 | gnutls_pkcs12_bag_set_data (gnutls_pkcs12_bag_t bag, | ||
343 | gnutls_pkcs12_bag_type_t type, | ||
344 | const gnutls_datum_t * data) | ||
345 | { | ||
346 | int ret; | ||
347 | if (bag == NULL) | ||
348 | { | ||
349 | gnutls_assert (); | ||
350 | return GNUTLS_E_INVALID_REQUEST; | ||
351 | } | ||
352 | |||
353 | if (bag->bag_elements == MAX_BAG_ELEMENTS - 1) | ||
354 | { | ||
355 | gnutls_assert (); | ||
356 | /* bag is full */ | ||
357 | return GNUTLS_E_MEMORY_ERROR; | ||
358 | } | ||
359 | |||
360 | if (bag->bag_elements == 1) | ||
361 | { | ||
362 | /* A bag with a key or an encrypted bag, must have | ||
363 | * only one element. | ||
364 | */ | ||
365 | |||
366 | if (bag->element[0].type == GNUTLS_BAG_PKCS8_KEY || | ||
367 | bag->element[0].type == GNUTLS_BAG_PKCS8_ENCRYPTED_KEY || | ||
368 | bag->element[0].type == GNUTLS_BAG_ENCRYPTED) | ||
369 | { | ||
370 | gnutls_assert (); | ||
371 | return GNUTLS_E_INVALID_REQUEST; | ||
372 | } | ||
373 | } | ||
374 | |||
375 | ret = | ||
376 | _gnutls_set_datum (&bag->element[bag->bag_elements].data, | ||
377 | data->data, data->size); | ||
378 | |||
379 | if (ret < 0) | ||
380 | { | ||
381 | gnutls_assert (); | ||
382 | return ret; | ||
383 | } | ||
384 | |||
385 | bag->element[bag->bag_elements].type = type; | ||
386 | |||
387 | bag->bag_elements++; | ||
388 | |||
389 | return bag->bag_elements - 1; | ||
390 | } | ||
391 | |||
392 | /** | ||
393 | * gnutls_pkcs12_bag_set_crt - This function inserts a certificate into the bag | ||
394 | * @bag: The bag | ||
395 | * @crt: the certificate to be copied. | ||
396 | * | ||
397 | * This function will insert the given certificate into the | ||
398 | * bag. This is just a wrapper over gnutls_pkcs12_bag_set_data(). | ||
399 | * | ||
400 | * Returns the index of the added bag on success, or a negative | ||
401 | * value on failure. | ||
402 | * | ||
403 | **/ | ||
404 | int | ||
405 | gnutls_pkcs12_bag_set_crt (gnutls_pkcs12_bag_t bag, gnutls_x509_crt_t crt) | ||
406 | { | ||
407 | int ret; | ||
408 | gnutls_datum_t data; | ||
409 | |||
410 | if (bag == NULL) | ||
411 | { | ||
412 | gnutls_assert (); | ||
413 | return GNUTLS_E_INVALID_REQUEST; | ||
414 | } | ||
415 | |||
416 | ret = _gnutls_x509_der_encode (crt->cert, "", &data, 0); | ||
417 | if (ret < 0) | ||
418 | { | ||
419 | gnutls_assert (); | ||
420 | return ret; | ||
421 | } | ||
422 | |||
423 | ret = gnutls_pkcs12_bag_set_data (bag, GNUTLS_BAG_CERTIFICATE, &data); | ||
424 | |||
425 | _gnutls_free_datum (&data); | ||
426 | |||
427 | return ret; | ||
428 | } | ||
429 | |||
430 | /** | ||
431 | * gnutls_pkcs12_bag_set_crl - This function inserts the CRL into the bag | ||
432 | * @bag: The bag | ||
433 | * @crl: the CRL to be copied. | ||
434 | * | ||
435 | * This function will insert the given CRL into the | ||
436 | * bag. This is just a wrapper over gnutls_pkcs12_bag_set_data(). | ||
437 | * | ||
438 | * Returns the index of the added bag on success, or a negative | ||
439 | * value on failure. | ||
440 | * | ||
441 | **/ | ||
442 | int | ||
443 | gnutls_pkcs12_bag_set_crl (gnutls_pkcs12_bag_t bag, gnutls_x509_crl_t crl) | ||
444 | { | ||
445 | int ret; | ||
446 | gnutls_datum_t data; | ||
447 | |||
448 | |||
449 | if (bag == NULL) | ||
450 | { | ||
451 | gnutls_assert (); | ||
452 | return GNUTLS_E_INVALID_REQUEST; | ||
453 | } | ||
454 | |||
455 | ret = _gnutls_x509_der_encode (crl->crl, "", &data, 0); | ||
456 | if (ret < 0) | ||
457 | { | ||
458 | gnutls_assert (); | ||
459 | return ret; | ||
460 | } | ||
461 | |||
462 | ret = gnutls_pkcs12_bag_set_data (bag, GNUTLS_BAG_CRL, &data); | ||
463 | |||
464 | _gnutls_free_datum (&data); | ||
465 | |||
466 | return ret; | ||
467 | } | ||
468 | |||
469 | /** | ||
470 | * gnutls_pkcs12_bag_set_key_id - This function sets a key ID into the bag element | ||
471 | * @bag: The bag | ||
472 | * @indx: The bag's element to add the id | ||
473 | * @id: the ID | ||
474 | * | ||
475 | * This function will add the given key ID, to the specified, by the index, bag | ||
476 | * element. The key ID will be encoded as a 'Local key identifier' bag attribute, | ||
477 | * which is usually used to distinguish the local private key and the certificate pair. | ||
478 | * | ||
479 | * Returns 0 on success, or a negative value on error. | ||
480 | * | ||
481 | **/ | ||
482 | int | ||
483 | gnutls_pkcs12_bag_set_key_id (gnutls_pkcs12_bag_t bag, int indx, | ||
484 | const gnutls_datum_t * id) | ||
485 | { | ||
486 | int ret; | ||
487 | |||
488 | |||
489 | if (bag == NULL) | ||
490 | { | ||
491 | gnutls_assert (); | ||
492 | return GNUTLS_E_INVALID_REQUEST; | ||
493 | } | ||
494 | |||
495 | if (indx > bag->bag_elements - 1) | ||
496 | { | ||
497 | gnutls_assert (); | ||
498 | return GNUTLS_E_INVALID_REQUEST; | ||
499 | } | ||
500 | |||
501 | ret = _gnutls_set_datum (&bag->element[indx].local_key_id, | ||
502 | id->data, id->size); | ||
503 | |||
504 | if (ret < 0) | ||
505 | { | ||
506 | gnutls_assert (); | ||
507 | return ret; | ||
508 | } | ||
509 | |||
510 | return 0; | ||
511 | } | ||
512 | |||
513 | /** | ||
514 | * gnutls_pkcs12_bag_get_key_id - This function gets the key ID from the bag element | ||
515 | * @bag: The bag | ||
516 | * @indx: The bag's element to add the id | ||
517 | * @id: where the ID will be copied (to be treated as const) | ||
518 | * | ||
519 | * This function will return the key ID, of the specified bag element. | ||
520 | * The key ID is usually used to distinguish the local private key and the certificate pair. | ||
521 | * | ||
522 | * Returns 0 on success, or a negative value on error. | ||
523 | * | ||
524 | **/ | ||
525 | int | ||
526 | gnutls_pkcs12_bag_get_key_id (gnutls_pkcs12_bag_t bag, int indx, | ||
527 | gnutls_datum_t * id) | ||
528 | { | ||
529 | if (bag == NULL) | ||
530 | { | ||
531 | gnutls_assert (); | ||
532 | return GNUTLS_E_INVALID_REQUEST; | ||
533 | } | ||
534 | |||
535 | if (indx > bag->bag_elements - 1) | ||
536 | { | ||
537 | gnutls_assert (); | ||
538 | return GNUTLS_E_INVALID_REQUEST; | ||
539 | } | ||
540 | |||
541 | id->data = bag->element[indx].local_key_id.data; | ||
542 | id->size = bag->element[indx].local_key_id.size; | ||
543 | |||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | /** | ||
548 | * gnutls_pkcs12_bag_get_friendly_name - This function returns the friendly name of the bag element | ||
549 | * @bag: The bag | ||
550 | * @indx: The bag's element to add the id | ||
551 | * @name: will hold a pointer to the name (to be treated as const) | ||
552 | * | ||
553 | * This function will return the friendly name, of the specified bag element. | ||
554 | * The key ID is usually used to distinguish the local private key and the certificate pair. | ||
555 | * | ||
556 | * Returns 0 on success, or a negative value on error. | ||
557 | * | ||
558 | **/ | ||
559 | int | ||
560 | gnutls_pkcs12_bag_get_friendly_name (gnutls_pkcs12_bag_t bag, int indx, | ||
561 | char **name) | ||
562 | { | ||
563 | if (bag == NULL) | ||
564 | { | ||
565 | gnutls_assert (); | ||
566 | return GNUTLS_E_INVALID_REQUEST; | ||
567 | } | ||
568 | |||
569 | if (indx > bag->bag_elements - 1) | ||
570 | { | ||
571 | gnutls_assert (); | ||
572 | return GNUTLS_E_INVALID_REQUEST; | ||
573 | } | ||
574 | |||
575 | *name = bag->element[indx].friendly_name; | ||
576 | |||
577 | return 0; | ||
578 | } | ||
579 | |||
580 | |||
581 | /** | ||
582 | * gnutls_pkcs12_bag_set_friendly_name - This function sets a friendly name into the bag element | ||
583 | * @bag: The bag | ||
584 | * @indx: The bag's element to add the id | ||
585 | * @name: the name | ||
586 | * | ||
587 | * This function will add the given key friendly name, to the specified, by the index, bag | ||
588 | * element. The name will be encoded as a 'Friendly name' bag attribute, | ||
589 | * which is usually used to set a user name to the local private key and the certificate pair. | ||
590 | * | ||
591 | * Returns 0 on success, or a negative value on error. | ||
592 | * | ||
593 | **/ | ||
594 | int | ||
595 | gnutls_pkcs12_bag_set_friendly_name (gnutls_pkcs12_bag_t bag, int indx, | ||
596 | const char *name) | ||
597 | { | ||
598 | if (bag == NULL) | ||
599 | { | ||
600 | gnutls_assert (); | ||
601 | return GNUTLS_E_INVALID_REQUEST; | ||
602 | } | ||
603 | |||
604 | if (indx > bag->bag_elements - 1) | ||
605 | { | ||
606 | gnutls_assert (); | ||
607 | return GNUTLS_E_INVALID_REQUEST; | ||
608 | } | ||
609 | |||
610 | bag->element[indx].friendly_name = gnutls_strdup (name); | ||
611 | |||
612 | if (name == NULL) | ||
613 | { | ||
614 | gnutls_assert (); | ||
615 | return GNUTLS_E_MEMORY_ERROR; | ||
616 | } | ||
617 | |||
618 | return 0; | ||
619 | } | ||
620 | |||
621 | |||
622 | /** | ||
623 | * gnutls_pkcs12_bag_decrypt - This function will decrypt an encrypted bag | ||
624 | * @bag: The bag | ||
625 | * @pass: The password used for encryption. This can only be ASCII. | ||
626 | * | ||
627 | * This function will decrypt the given encrypted bag and return 0 on success. | ||
628 | * | ||
629 | **/ | ||
630 | int | ||
631 | gnutls_pkcs12_bag_decrypt (gnutls_pkcs12_bag_t bag, const char *pass) | ||
632 | { | ||
633 | int ret; | ||
634 | gnutls_datum_t dec; | ||
635 | |||
636 | if (bag == NULL) | ||
637 | { | ||
638 | gnutls_assert (); | ||
639 | return GNUTLS_E_INVALID_REQUEST; | ||
640 | } | ||
641 | |||
642 | if (bag->element[0].type != GNUTLS_BAG_ENCRYPTED) | ||
643 | { | ||
644 | gnutls_assert (); | ||
645 | return GNUTLS_E_INVALID_REQUEST; | ||
646 | } | ||
647 | |||
648 | ret = _gnutls_pkcs7_decrypt_data (&bag->element[0].data, pass, &dec); | ||
649 | |||
650 | if (ret < 0) | ||
651 | { | ||
652 | gnutls_assert (); | ||
653 | return ret; | ||
654 | } | ||
655 | |||
656 | /* decryption succeeded. Now decode the SafeContents | ||
657 | * stuff, and parse it. | ||
658 | */ | ||
659 | |||
660 | _gnutls_free_datum (&bag->element[0].data); | ||
661 | |||
662 | ret = _pkcs12_decode_safe_contents (&dec, bag); | ||
663 | |||
664 | _gnutls_free_datum (&dec); | ||
665 | |||
666 | if (ret < 0) | ||
667 | { | ||
668 | gnutls_assert (); | ||
669 | return ret; | ||
670 | } | ||
671 | |||
672 | return 0; | ||
673 | } | ||
674 | |||
675 | /** | ||
676 | * gnutls_pkcs12_bag_encrypt - This function will encrypt a bag | ||
677 | * @bag: The bag | ||
678 | * @pass: The password used for encryption. This can only be ASCII. | ||
679 | * @flags: should be one of gnutls_pkcs_encrypt_flags_t elements bitwise or'd | ||
680 | * | ||
681 | * This function will encrypt the given bag and return 0 on success. | ||
682 | * | ||
683 | **/ | ||
684 | int | ||
685 | gnutls_pkcs12_bag_encrypt (gnutls_pkcs12_bag_t bag, const char *pass, | ||
686 | unsigned int flags) | ||
687 | { | ||
688 | int ret; | ||
689 | ASN1_TYPE safe_cont = ASN1_TYPE_EMPTY; | ||
690 | gnutls_datum_t der = { NULL, 0 }; | ||
691 | gnutls_datum_t enc = { NULL, 0 }; | ||
692 | schema_id id; | ||
693 | |||
694 | if (bag == NULL) | ||
695 | { | ||
696 | gnutls_assert (); | ||
697 | return GNUTLS_E_INVALID_REQUEST; | ||
698 | } | ||
699 | |||
700 | if (bag->element[0].type == GNUTLS_BAG_ENCRYPTED) | ||
701 | { | ||
702 | gnutls_assert (); | ||
703 | return GNUTLS_E_INVALID_REQUEST; | ||
704 | } | ||
705 | |||
706 | /* Encode the whole bag to a safe contents | ||
707 | * structure. | ||
708 | */ | ||
709 | ret = _pkcs12_encode_safe_contents (bag, &safe_cont, NULL); | ||
710 | if (ret < 0) | ||
711 | { | ||
712 | gnutls_assert (); | ||
713 | return ret; | ||
714 | } | ||
715 | |||
716 | /* DER encode the SafeContents. | ||
717 | */ | ||
718 | ret = _gnutls_x509_der_encode (safe_cont, "", &der, 0); | ||
719 | |||
720 | asn1_delete_structure (&safe_cont); | ||
721 | |||
722 | if (ret < 0) | ||
723 | { | ||
724 | gnutls_assert (); | ||
725 | return ret; | ||
726 | } | ||
727 | |||
728 | if (flags & GNUTLS_PKCS_PLAIN) | ||
729 | { | ||
730 | gnutls_assert (); | ||
731 | return GNUTLS_E_INVALID_REQUEST; | ||
732 | } | ||
733 | |||
734 | if (flags & GNUTLS_PKCS_USE_PKCS12_ARCFOUR) | ||
735 | id = PKCS12_ARCFOUR_SHA1; | ||
736 | else if (flags & GNUTLS_PKCS_USE_PKCS12_RC2_40) | ||
737 | id = PKCS12_RC2_40_SHA1; | ||
738 | else if (flags & GNUTLS_PKCS_USE_PBES2_3DES) | ||
739 | id = PBES2; | ||
740 | else | ||
741 | id = PKCS12_3DES_SHA1; | ||
742 | |||
743 | /* Now encrypt them. | ||
744 | */ | ||
745 | ret = _gnutls_pkcs7_encrypt_data (id, &der, pass, &enc); | ||
746 | |||
747 | _gnutls_free_datum (&der); | ||
748 | |||
749 | if (ret < 0) | ||
750 | { | ||
751 | gnutls_assert (); | ||
752 | return ret; | ||
753 | } | ||
754 | |||
755 | /* encryption succeeded. | ||
756 | */ | ||
757 | |||
758 | _pkcs12_bag_free_data (bag); | ||
759 | |||
760 | bag->element[0].type = GNUTLS_BAG_ENCRYPTED; | ||
761 | bag->element[0].data = enc; | ||
762 | |||
763 | bag->bag_elements = 1; | ||
764 | |||
765 | |||
766 | return 0; | ||
767 | } | ||
768 | |||
769 | |||
770 | #endif /* ENABLE_PKI */ | ||
diff --git a/src/daemon/https/x509/pkcs12_encr.c b/src/daemon/https/x509/pkcs12_encr.c new file mode 100644 index 00000000..c80d23a3 --- /dev/null +++ b/src/daemon/https/x509/pkcs12_encr.c | |||
@@ -0,0 +1,169 @@ | |||
1 | /* minip12.c - A mini pkcs-12 implementation (modified for gnutls) | ||
2 | * | ||
3 | * Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. | ||
4 | * | ||
5 | * This file is part of GNUTLS. | ||
6 | * | ||
7 | * The GNUTLS library is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU Lesser General Public License | ||
9 | * as published by the Free Software Foundation; either version 2.1 of | ||
10 | * the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This library is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public | ||
18 | * License along with this library; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
20 | * USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <gnutls_int.h> | ||
25 | |||
26 | #ifdef ENABLE_PKI | ||
27 | |||
28 | #include <gcrypt.h> | ||
29 | #include <gc.h> | ||
30 | #include <gnutls_errors.h> | ||
31 | |||
32 | /* Returns 0 if the password is ok, or a negative error | ||
33 | * code instead. | ||
34 | */ | ||
35 | static int | ||
36 | _pkcs12_check_pass (const char *pass, size_t plen) | ||
37 | { | ||
38 | const unsigned char *p = pass; | ||
39 | unsigned int i; | ||
40 | |||
41 | for (i = 0; i < plen; i++) | ||
42 | { | ||
43 | if (isascii (p[i])) | ||
44 | continue; | ||
45 | return GNUTLS_E_INVALID_PASSWORD; | ||
46 | } | ||
47 | |||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | /* ID should be: | ||
52 | * 3 for MAC | ||
53 | * 2 for IV | ||
54 | * 1 for encryption key | ||
55 | */ | ||
56 | int | ||
57 | _pkcs12_string_to_key (unsigned int id, const opaque * salt, | ||
58 | unsigned int salt_size, unsigned int iter, | ||
59 | const char *pw, unsigned int req_keylen, | ||
60 | opaque * keybuf) | ||
61 | { | ||
62 | int rc; | ||
63 | unsigned int i, j; | ||
64 | gc_hash_handle md; | ||
65 | mpi_t num_b1 = NULL; | ||
66 | unsigned int pwlen; | ||
67 | opaque hash[20], buf_b[64], buf_i[128], *p; | ||
68 | size_t cur_keylen; | ||
69 | size_t n; | ||
70 | |||
71 | cur_keylen = 0; | ||
72 | |||
73 | if (pw == NULL) | ||
74 | pwlen = 0; | ||
75 | else | ||
76 | pwlen = strlen (pw); | ||
77 | |||
78 | if (pwlen > 63 / 2) | ||
79 | { | ||
80 | gnutls_assert (); | ||
81 | return GNUTLS_E_INVALID_REQUEST; | ||
82 | } | ||
83 | |||
84 | if ((rc = _pkcs12_check_pass (pw, pwlen)) < 0) | ||
85 | { | ||
86 | gnutls_assert (); | ||
87 | return rc; | ||
88 | } | ||
89 | |||
90 | /* Store salt and password in BUF_I */ | ||
91 | p = buf_i; | ||
92 | for (i = 0; i < 64; i++) | ||
93 | *p++ = salt[i % salt_size]; | ||
94 | if (pw) | ||
95 | { | ||
96 | for (i = j = 0; i < 64; i += 2) | ||
97 | { | ||
98 | *p++ = 0; | ||
99 | *p++ = pw[j]; | ||
100 | if (++j > pwlen) /* Note, that we include the trailing zero */ | ||
101 | j = 0; | ||
102 | } | ||
103 | } | ||
104 | else | ||
105 | memset (p, 0, 64); | ||
106 | |||
107 | for (;;) | ||
108 | { | ||
109 | rc = gc_hash_open (GC_SHA1, 0, &md); | ||
110 | if (rc) | ||
111 | { | ||
112 | gnutls_assert (); | ||
113 | return GNUTLS_E_DECRYPTION_FAILED; | ||
114 | } | ||
115 | for (i = 0; i < 64; i++) | ||
116 | { | ||
117 | unsigned char lid = id & 0xFF; | ||
118 | gc_hash_write (md, 1, &lid); | ||
119 | } | ||
120 | gc_hash_write (md, pw ? 128 : 64, buf_i); | ||
121 | memcpy (hash, gc_hash_read (md), 20); | ||
122 | gc_hash_close (md); | ||
123 | for (i = 1; i < iter; i++) | ||
124 | gc_hash_buffer (GC_SHA1, hash, 20, hash); | ||
125 | for (i = 0; i < 20 && cur_keylen < req_keylen; i++) | ||
126 | keybuf[cur_keylen++] = hash[i]; | ||
127 | if (cur_keylen == req_keylen) | ||
128 | { | ||
129 | gcry_mpi_release (num_b1); | ||
130 | return 0; /* ready */ | ||
131 | } | ||
132 | |||
133 | /* need more bytes. */ | ||
134 | for (i = 0; i < 64; i++) | ||
135 | buf_b[i] = hash[i % 20]; | ||
136 | n = 64; | ||
137 | rc = _gnutls_mpi_scan (&num_b1, buf_b, &n); | ||
138 | if (rc < 0) | ||
139 | { | ||
140 | gnutls_assert (); | ||
141 | return rc; | ||
142 | } | ||
143 | gcry_mpi_add_ui (num_b1, num_b1, 1); | ||
144 | for (i = 0; i < 128; i += 64) | ||
145 | { | ||
146 | mpi_t num_ij; | ||
147 | |||
148 | n = 64; | ||
149 | rc = _gnutls_mpi_scan (&num_ij, buf_i + i, &n); | ||
150 | if (rc < 0) | ||
151 | { | ||
152 | gnutls_assert (); | ||
153 | return rc; | ||
154 | } | ||
155 | gcry_mpi_add (num_ij, num_ij, num_b1); | ||
156 | gcry_mpi_clear_highbit (num_ij, 64 * 8); | ||
157 | n = 64; | ||
158 | rc = _gnutls_mpi_print (buf_i + i, &n, num_ij); | ||
159 | if (rc < 0) | ||
160 | { | ||
161 | gnutls_assert (); | ||
162 | return rc; | ||
163 | } | ||
164 | gcry_mpi_release (num_ij); | ||
165 | } | ||
166 | } | ||
167 | } | ||
168 | |||
169 | #endif /* ENABLE_PKI */ | ||
diff --git a/src/daemon/https/x509/pkcs7.c b/src/daemon/https/x509/pkcs7.c new file mode 100644 index 00000000..35f21b12 --- /dev/null +++ b/src/daemon/https/x509/pkcs7.c | |||
@@ -0,0 +1,1023 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | /* Functions that relate on PKCS7 certificate lists parsing. | ||
26 | */ | ||
27 | |||
28 | #include <gnutls_int.h> | ||
29 | #include <libtasn1.h> | ||
30 | |||
31 | #ifdef ENABLE_PKI | ||
32 | |||
33 | #include <gnutls_datum.h> | ||
34 | #include <gnutls_global.h> | ||
35 | #include <gnutls_errors.h> | ||
36 | #include <common.h> | ||
37 | #include <x509_b64.h> | ||
38 | #include <pkcs7.h> | ||
39 | #include <dn.h> | ||
40 | |||
41 | #define SIGNED_DATA_OID "1.2.840.113549.1.7.2" | ||
42 | |||
43 | /* Decodes the PKCS #7 signed data, and returns an ASN1_TYPE, | ||
44 | * which holds them. If raw is non null then the raw decoded | ||
45 | * data are copied (they are locally allocated) there. | ||
46 | */ | ||
47 | static int | ||
48 | _decode_pkcs7_signed_data (ASN1_TYPE pkcs7, ASN1_TYPE * sdata, | ||
49 | gnutls_datum_t * raw) | ||
50 | { | ||
51 | char oid[128]; | ||
52 | ASN1_TYPE c2; | ||
53 | opaque *tmp = NULL; | ||
54 | int tmp_size, len, result; | ||
55 | |||
56 | len = sizeof (oid) - 1; | ||
57 | result = asn1_read_value (pkcs7, "contentType", oid, &len); | ||
58 | if (result != ASN1_SUCCESS) | ||
59 | { | ||
60 | gnutls_assert (); | ||
61 | return _gnutls_asn2err (result); | ||
62 | } | ||
63 | |||
64 | if (strcmp (oid, SIGNED_DATA_OID) != 0) | ||
65 | { | ||
66 | gnutls_assert (); | ||
67 | _gnutls_x509_log ("Unknown PKCS7 Content OID '%s'\n", oid); | ||
68 | return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE; | ||
69 | } | ||
70 | |||
71 | if ((result = asn1_create_element | ||
72 | (_gnutls_get_pkix (), "PKIX1.pkcs-7-SignedData", &c2)) != ASN1_SUCCESS) | ||
73 | { | ||
74 | gnutls_assert (); | ||
75 | return _gnutls_asn2err (result); | ||
76 | } | ||
77 | |||
78 | /* the Signed-data has been created, so | ||
79 | * decode them. | ||
80 | */ | ||
81 | tmp_size = 0; | ||
82 | result = asn1_read_value (pkcs7, "content", NULL, &tmp_size); | ||
83 | if (result != ASN1_MEM_ERROR) | ||
84 | { | ||
85 | gnutls_assert (); | ||
86 | result = _gnutls_asn2err (result); | ||
87 | goto cleanup; | ||
88 | } | ||
89 | |||
90 | tmp = gnutls_malloc (tmp_size); | ||
91 | if (tmp == NULL) | ||
92 | { | ||
93 | gnutls_assert (); | ||
94 | result = GNUTLS_E_MEMORY_ERROR; | ||
95 | goto cleanup; | ||
96 | } | ||
97 | |||
98 | result = asn1_read_value (pkcs7, "content", tmp, &tmp_size); | ||
99 | if (result != ASN1_SUCCESS) | ||
100 | { | ||
101 | gnutls_assert (); | ||
102 | result = _gnutls_asn2err (result); | ||
103 | goto cleanup; | ||
104 | } | ||
105 | |||
106 | /* tmp, tmp_size hold the data and the size of the CertificateSet structure | ||
107 | * actually the ANY stuff. | ||
108 | */ | ||
109 | |||
110 | /* Step 1. In case of a signed structure extract certificate set. | ||
111 | */ | ||
112 | |||
113 | result = asn1_der_decoding (&c2, tmp, tmp_size, NULL); | ||
114 | if (result != ASN1_SUCCESS) | ||
115 | { | ||
116 | gnutls_assert (); | ||
117 | result = _gnutls_asn2err (result); | ||
118 | goto cleanup; | ||
119 | } | ||
120 | |||
121 | if (raw == NULL) | ||
122 | { | ||
123 | gnutls_free (tmp); | ||
124 | } | ||
125 | else | ||
126 | { | ||
127 | raw->data = tmp; | ||
128 | raw->size = tmp_size; | ||
129 | } | ||
130 | |||
131 | *sdata = c2; | ||
132 | |||
133 | return 0; | ||
134 | |||
135 | cleanup: | ||
136 | if (c2) | ||
137 | asn1_delete_structure (&c2); | ||
138 | gnutls_free (tmp); | ||
139 | return result; | ||
140 | } | ||
141 | |||
142 | /** | ||
143 | * gnutls_pkcs7_init - This function initializes a gnutls_pkcs7_t structure | ||
144 | * @pkcs7: The structure to be initialized | ||
145 | * | ||
146 | * This function will initialize a PKCS7 structure. PKCS7 structures | ||
147 | * usually contain lists of X.509 Certificates and X.509 Certificate | ||
148 | * revocation lists. | ||
149 | * | ||
150 | * Returns 0 on success. | ||
151 | * | ||
152 | **/ | ||
153 | int | ||
154 | gnutls_pkcs7_init (gnutls_pkcs7_t * pkcs7) | ||
155 | { | ||
156 | *pkcs7 = gnutls_calloc (1, sizeof (gnutls_pkcs7_int)); | ||
157 | |||
158 | if (*pkcs7) | ||
159 | { | ||
160 | int result = asn1_create_element (_gnutls_get_pkix (), | ||
161 | "PKIX1.pkcs-7-ContentInfo", | ||
162 | &(*pkcs7)->pkcs7); | ||
163 | if (result != ASN1_SUCCESS) | ||
164 | { | ||
165 | gnutls_assert (); | ||
166 | gnutls_free (*pkcs7); | ||
167 | return _gnutls_asn2err (result); | ||
168 | } | ||
169 | return 0; /* success */ | ||
170 | } | ||
171 | return GNUTLS_E_MEMORY_ERROR; | ||
172 | } | ||
173 | |||
174 | /** | ||
175 | * gnutls_pkcs7_deinit - This function deinitializes memory used by a gnutls_pkcs7_t structure | ||
176 | * @pkcs7: The structure to be initialized | ||
177 | * | ||
178 | * This function will deinitialize a PKCS7 structure. | ||
179 | * | ||
180 | **/ | ||
181 | void | ||
182 | gnutls_pkcs7_deinit (gnutls_pkcs7_t pkcs7) | ||
183 | { | ||
184 | if (!pkcs7) | ||
185 | return; | ||
186 | |||
187 | if (pkcs7->pkcs7) | ||
188 | asn1_delete_structure (&pkcs7->pkcs7); | ||
189 | |||
190 | gnutls_free (pkcs7); | ||
191 | } | ||
192 | |||
193 | /** | ||
194 | * gnutls_pkcs7_import - This function will import a DER or PEM encoded PKCS7 | ||
195 | * @pkcs7: The structure to store the parsed PKCS7. | ||
196 | * @data: The DER or PEM encoded PKCS7. | ||
197 | * @format: One of DER or PEM | ||
198 | * | ||
199 | * This function will convert the given DER or PEM encoded PKCS7 | ||
200 | * to the native gnutls_pkcs7_t format. The output will be stored in 'pkcs7'. | ||
201 | * | ||
202 | * If the PKCS7 is PEM encoded it should have a header of "PKCS7". | ||
203 | * | ||
204 | * Returns 0 on success. | ||
205 | * | ||
206 | **/ | ||
207 | int | ||
208 | gnutls_pkcs7_import (gnutls_pkcs7_t pkcs7, const gnutls_datum_t * data, | ||
209 | gnutls_x509_crt_fmt_t format) | ||
210 | { | ||
211 | int result = 0, need_free = 0; | ||
212 | gnutls_datum_t _data; | ||
213 | |||
214 | if (pkcs7 == NULL) | ||
215 | return GNUTLS_E_INVALID_REQUEST; | ||
216 | |||
217 | _data.data = data->data; | ||
218 | _data.size = data->size; | ||
219 | |||
220 | /* If the PKCS7 is in PEM format then decode it | ||
221 | */ | ||
222 | if (format == GNUTLS_X509_FMT_PEM) | ||
223 | { | ||
224 | opaque *out; | ||
225 | |||
226 | result = _gnutls_fbase64_decode (PEM_PKCS7, data->data, data->size, | ||
227 | &out); | ||
228 | |||
229 | if (result <= 0) | ||
230 | { | ||
231 | if (result == 0) | ||
232 | result = GNUTLS_E_INTERNAL_ERROR; | ||
233 | gnutls_assert (); | ||
234 | return result; | ||
235 | } | ||
236 | |||
237 | _data.data = out; | ||
238 | _data.size = result; | ||
239 | |||
240 | need_free = 1; | ||
241 | } | ||
242 | |||
243 | |||
244 | result = asn1_der_decoding (&pkcs7->pkcs7, _data.data, _data.size, NULL); | ||
245 | if (result != ASN1_SUCCESS) | ||
246 | { | ||
247 | result = _gnutls_asn2err (result); | ||
248 | gnutls_assert (); | ||
249 | goto cleanup; | ||
250 | } | ||
251 | |||
252 | if (need_free) | ||
253 | _gnutls_free_datum (&_data); | ||
254 | |||
255 | return 0; | ||
256 | |||
257 | cleanup: | ||
258 | if (need_free) | ||
259 | _gnutls_free_datum (&_data); | ||
260 | return result; | ||
261 | } | ||
262 | |||
263 | /** | ||
264 | * gnutls_pkcs7_get_crt_raw - This function returns a certificate in a PKCS7 certificate set | ||
265 | * @pkcs7_struct: should contain a gnutls_pkcs7_t structure | ||
266 | * @indx: contains the index of the certificate to extract | ||
267 | * @certificate: the contents of the certificate will be copied there (may be null) | ||
268 | * @certificate_size: should hold the size of the certificate | ||
269 | * | ||
270 | * This function will return a certificate of the PKCS7 or RFC2630 certificate set. | ||
271 | * Returns 0 on success. If the provided buffer is not long enough, | ||
272 | * then @certificate_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER is returned. | ||
273 | * | ||
274 | * After the last certificate has been read GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE | ||
275 | * will be returned. | ||
276 | * | ||
277 | **/ | ||
278 | int | ||
279 | gnutls_pkcs7_get_crt_raw (gnutls_pkcs7_t pkcs7, | ||
280 | int indx, void *certificate, | ||
281 | size_t * certificate_size) | ||
282 | { | ||
283 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
284 | int result, len; | ||
285 | char root2[MAX_NAME_SIZE]; | ||
286 | char oid[128]; | ||
287 | gnutls_datum_t tmp = { NULL, 0 }; | ||
288 | |||
289 | if (certificate_size == NULL || pkcs7 == NULL) | ||
290 | return GNUTLS_E_INVALID_REQUEST; | ||
291 | |||
292 | /* Step 1. decode the signed data. | ||
293 | */ | ||
294 | result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, &tmp); | ||
295 | if (result < 0) | ||
296 | { | ||
297 | gnutls_assert (); | ||
298 | return result; | ||
299 | } | ||
300 | |||
301 | /* Step 2. Parse the CertificateSet | ||
302 | */ | ||
303 | |||
304 | snprintf (root2, sizeof (root2), "certificates.?%u", indx + 1); | ||
305 | |||
306 | len = sizeof (oid) - 1; | ||
307 | |||
308 | result = asn1_read_value (c2, root2, oid, &len); | ||
309 | |||
310 | if (result == ASN1_VALUE_NOT_FOUND) | ||
311 | { | ||
312 | result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
313 | goto cleanup; | ||
314 | } | ||
315 | |||
316 | if (result != ASN1_SUCCESS) | ||
317 | { | ||
318 | gnutls_assert (); | ||
319 | result = _gnutls_asn2err (result); | ||
320 | goto cleanup; | ||
321 | } | ||
322 | |||
323 | /* if 'Certificate' is the choice found: | ||
324 | */ | ||
325 | if (strcmp (oid, "certificate") == 0) | ||
326 | { | ||
327 | int start, end; | ||
328 | |||
329 | result = asn1_der_decoding_startEnd (c2, tmp.data, tmp.size, | ||
330 | root2, &start, &end); | ||
331 | |||
332 | if (result != ASN1_SUCCESS) | ||
333 | { | ||
334 | gnutls_assert (); | ||
335 | result = _gnutls_asn2err (result); | ||
336 | goto cleanup; | ||
337 | } | ||
338 | |||
339 | end = end - start + 1; | ||
340 | |||
341 | if ((unsigned) end > *certificate_size) | ||
342 | { | ||
343 | *certificate_size = end; | ||
344 | result = GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
345 | goto cleanup; | ||
346 | } | ||
347 | |||
348 | if (certificate) | ||
349 | memcpy (certificate, &tmp.data[start], end); | ||
350 | |||
351 | *certificate_size = end; | ||
352 | |||
353 | result = 0; | ||
354 | |||
355 | } | ||
356 | else | ||
357 | { | ||
358 | result = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE; | ||
359 | } | ||
360 | |||
361 | cleanup: | ||
362 | _gnutls_free_datum (&tmp); | ||
363 | if (c2) | ||
364 | asn1_delete_structure (&c2); | ||
365 | return result; | ||
366 | } | ||
367 | |||
368 | /** | ||
369 | * gnutls_pkcs7_get_crt_count - This function returns the number of certificates in a PKCS7 certificate set | ||
370 | * @pkcs7_struct: should contain a gnutls_pkcs7_t structure | ||
371 | * | ||
372 | * This function will return the number of certifcates in the PKCS7 or | ||
373 | * RFC2630 certificate set. | ||
374 | * | ||
375 | * Returns a negative value on failure. | ||
376 | * | ||
377 | **/ | ||
378 | int | ||
379 | gnutls_pkcs7_get_crt_count (gnutls_pkcs7_t pkcs7) | ||
380 | { | ||
381 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
382 | int result, count; | ||
383 | |||
384 | if (pkcs7 == NULL) | ||
385 | return GNUTLS_E_INVALID_REQUEST; | ||
386 | |||
387 | /* Step 1. decode the signed data. | ||
388 | */ | ||
389 | result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL); | ||
390 | if (result < 0) | ||
391 | { | ||
392 | gnutls_assert (); | ||
393 | return result; | ||
394 | } | ||
395 | |||
396 | /* Step 2. Count the CertificateSet */ | ||
397 | |||
398 | result = asn1_number_of_elements (c2, "certificates", &count); | ||
399 | |||
400 | asn1_delete_structure (&c2); | ||
401 | |||
402 | if (result != ASN1_SUCCESS) | ||
403 | { | ||
404 | gnutls_assert (); | ||
405 | return 0; /* no certificates */ | ||
406 | } | ||
407 | |||
408 | return count; | ||
409 | |||
410 | } | ||
411 | |||
412 | /** | ||
413 | * gnutls_pkcs7_export - This function will export the pkcs7 structure | ||
414 | * @pkcs7: Holds the pkcs7 structure | ||
415 | * @format: the format of output params. One of PEM or DER. | ||
416 | * @output_data: will contain a structure PEM or DER encoded | ||
417 | * @output_data_size: holds the size of output_data (and will be | ||
418 | * replaced by the actual size of parameters) | ||
419 | * | ||
420 | * This function will export the pkcs7 structure to DER or PEM format. | ||
421 | * | ||
422 | * If the buffer provided is not long enough to hold the output, then | ||
423 | * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will | ||
424 | * be returned. | ||
425 | * | ||
426 | * If the structure is PEM encoded, it will have a header | ||
427 | * of "BEGIN PKCS7". | ||
428 | * | ||
429 | * Return value: In case of failure a negative value will be | ||
430 | * returned, and 0 on success. | ||
431 | * | ||
432 | **/ | ||
433 | int | ||
434 | gnutls_pkcs7_export (gnutls_pkcs7_t pkcs7, | ||
435 | gnutls_x509_crt_fmt_t format, void *output_data, | ||
436 | size_t * output_data_size) | ||
437 | { | ||
438 | if (pkcs7 == NULL) | ||
439 | return GNUTLS_E_INVALID_REQUEST; | ||
440 | |||
441 | return _gnutls_x509_export_int (pkcs7->pkcs7, format, PEM_PKCS7, | ||
442 | output_data, output_data_size); | ||
443 | } | ||
444 | |||
445 | /* Creates an empty signed data structure in the pkcs7 | ||
446 | * structure and returns a handle to the signed data. | ||
447 | */ | ||
448 | static int | ||
449 | create_empty_signed_data (ASN1_TYPE pkcs7, ASN1_TYPE * sdata) | ||
450 | { | ||
451 | uint8_t one = 1; | ||
452 | int result; | ||
453 | |||
454 | *sdata = ASN1_TYPE_EMPTY; | ||
455 | |||
456 | if ((result = asn1_create_element | ||
457 | (_gnutls_get_pkix (), "PKIX1.pkcs-7-SignedData", | ||
458 | sdata)) != ASN1_SUCCESS) | ||
459 | { | ||
460 | gnutls_assert (); | ||
461 | result = _gnutls_asn2err (result); | ||
462 | goto cleanup; | ||
463 | } | ||
464 | |||
465 | /* Use version 1 | ||
466 | */ | ||
467 | result = asn1_write_value (*sdata, "version", &one, 1); | ||
468 | if (result != ASN1_SUCCESS) | ||
469 | { | ||
470 | gnutls_assert (); | ||
471 | result = _gnutls_asn2err (result); | ||
472 | goto cleanup; | ||
473 | } | ||
474 | |||
475 | /* Use no digest algorithms | ||
476 | */ | ||
477 | |||
478 | /* id-data */ | ||
479 | result = | ||
480 | asn1_write_value (*sdata, "encapContentInfo.eContentType", | ||
481 | "1.2.840.113549.1.7.5", 1); | ||
482 | if (result != ASN1_SUCCESS) | ||
483 | { | ||
484 | gnutls_assert (); | ||
485 | result = _gnutls_asn2err (result); | ||
486 | goto cleanup; | ||
487 | } | ||
488 | |||
489 | result = asn1_write_value (*sdata, "encapContentInfo.eContent", NULL, 0); | ||
490 | if (result != ASN1_SUCCESS) | ||
491 | { | ||
492 | gnutls_assert (); | ||
493 | result = _gnutls_asn2err (result); | ||
494 | goto cleanup; | ||
495 | } | ||
496 | |||
497 | /* Add no certificates. | ||
498 | */ | ||
499 | |||
500 | /* Add no crls. | ||
501 | */ | ||
502 | |||
503 | /* Add no signerInfos. | ||
504 | */ | ||
505 | |||
506 | /* Write the content type of the signed data | ||
507 | */ | ||
508 | result = asn1_write_value (pkcs7, "contentType", SIGNED_DATA_OID, 1); | ||
509 | if (result != ASN1_SUCCESS) | ||
510 | { | ||
511 | gnutls_assert (); | ||
512 | result = _gnutls_asn2err (result); | ||
513 | goto cleanup; | ||
514 | } | ||
515 | |||
516 | return 0; | ||
517 | |||
518 | cleanup: | ||
519 | asn1_delete_structure (sdata); | ||
520 | return result; | ||
521 | |||
522 | } | ||
523 | |||
524 | /** | ||
525 | * gnutls_pkcs7_set_crt_raw - This function adds a certificate in a PKCS7 certificate set | ||
526 | * @pkcs7_struct: should contain a gnutls_pkcs7_t structure | ||
527 | * @crt: the DER encoded certificate to be added | ||
528 | * | ||
529 | * This function will add a certificate to the PKCS7 or RFC2630 certificate set. | ||
530 | * Returns 0 on success. | ||
531 | * | ||
532 | **/ | ||
533 | int | ||
534 | gnutls_pkcs7_set_crt_raw (gnutls_pkcs7_t pkcs7, const gnutls_datum_t * crt) | ||
535 | { | ||
536 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
537 | int result; | ||
538 | |||
539 | if (pkcs7 == NULL) | ||
540 | return GNUTLS_E_INVALID_REQUEST; | ||
541 | |||
542 | /* Step 1. decode the signed data. | ||
543 | */ | ||
544 | result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL); | ||
545 | if (result < 0 && result != GNUTLS_E_ASN1_VALUE_NOT_FOUND) | ||
546 | { | ||
547 | gnutls_assert (); | ||
548 | return result; | ||
549 | } | ||
550 | |||
551 | /* If the signed data are uninitialized | ||
552 | * then create them. | ||
553 | */ | ||
554 | if (result == GNUTLS_E_ASN1_VALUE_NOT_FOUND) | ||
555 | { | ||
556 | /* The pkcs7 structure is new, so create the | ||
557 | * signedData. | ||
558 | */ | ||
559 | result = create_empty_signed_data (pkcs7->pkcs7, &c2); | ||
560 | if (result < 0) | ||
561 | { | ||
562 | gnutls_assert (); | ||
563 | return result; | ||
564 | } | ||
565 | } | ||
566 | |||
567 | /* Step 2. Append the new certificate. | ||
568 | */ | ||
569 | |||
570 | result = asn1_write_value (c2, "certificates", "NEW", 1); | ||
571 | if (result != ASN1_SUCCESS) | ||
572 | { | ||
573 | gnutls_assert (); | ||
574 | result = _gnutls_asn2err (result); | ||
575 | goto cleanup; | ||
576 | } | ||
577 | |||
578 | result = asn1_write_value (c2, "certificates.?LAST", "certificate", 1); | ||
579 | if (result != ASN1_SUCCESS) | ||
580 | { | ||
581 | gnutls_assert (); | ||
582 | result = _gnutls_asn2err (result); | ||
583 | goto cleanup; | ||
584 | } | ||
585 | |||
586 | result = | ||
587 | asn1_write_value (c2, "certificates.?LAST.certificate", crt->data, | ||
588 | crt->size); | ||
589 | if (result != ASN1_SUCCESS) | ||
590 | { | ||
591 | gnutls_assert (); | ||
592 | result = _gnutls_asn2err (result); | ||
593 | goto cleanup; | ||
594 | } | ||
595 | |||
596 | /* Step 3. Replace the old content with the new | ||
597 | */ | ||
598 | result = | ||
599 | _gnutls_x509_der_encode_and_copy (c2, "", pkcs7->pkcs7, "content", 0); | ||
600 | if (result < 0) | ||
601 | { | ||
602 | gnutls_assert (); | ||
603 | goto cleanup; | ||
604 | } | ||
605 | |||
606 | asn1_delete_structure (&c2); | ||
607 | |||
608 | return 0; | ||
609 | |||
610 | cleanup: | ||
611 | if (c2) | ||
612 | asn1_delete_structure (&c2); | ||
613 | return result; | ||
614 | } | ||
615 | |||
616 | /** | ||
617 | * gnutls_pkcs7_set_crt - This function adds a parsed certificate in a PKCS7 certificate set | ||
618 | * @pkcs7_struct: should contain a gnutls_pkcs7_t structure | ||
619 | * @crt: the certificate to be copied. | ||
620 | * | ||
621 | * This function will add a parsed certificate to the PKCS7 or RFC2630 certificate set. | ||
622 | * This is a wrapper function over gnutls_pkcs7_set_crt_raw() . | ||
623 | * | ||
624 | * Returns 0 on success. | ||
625 | * | ||
626 | **/ | ||
627 | int | ||
628 | gnutls_pkcs7_set_crt (gnutls_pkcs7_t pkcs7, gnutls_x509_crt_t crt) | ||
629 | { | ||
630 | int ret; | ||
631 | gnutls_datum_t data; | ||
632 | |||
633 | if (pkcs7 == NULL) | ||
634 | return GNUTLS_E_INVALID_REQUEST; | ||
635 | |||
636 | ret = _gnutls_x509_der_encode (crt->cert, "", &data, 0); | ||
637 | if (ret < 0) | ||
638 | { | ||
639 | gnutls_assert (); | ||
640 | return ret; | ||
641 | } | ||
642 | |||
643 | ret = gnutls_pkcs7_set_crt_raw (pkcs7, &data); | ||
644 | |||
645 | _gnutls_free_datum (&data); | ||
646 | |||
647 | if (ret < 0) | ||
648 | { | ||
649 | gnutls_assert (); | ||
650 | return ret; | ||
651 | } | ||
652 | |||
653 | return 0; | ||
654 | } | ||
655 | |||
656 | |||
657 | /** | ||
658 | * gnutls_pkcs7_delete_crt - This function deletes a certificate from a PKCS7 certificate set | ||
659 | * @pkcs7_struct: should contain a gnutls_pkcs7_t structure | ||
660 | * @indx: the index of the certificate to delete | ||
661 | * | ||
662 | * This function will delete a certificate from a PKCS7 or RFC2630 certificate set. | ||
663 | * Index starts from 0. Returns 0 on success. | ||
664 | * | ||
665 | **/ | ||
666 | int | ||
667 | gnutls_pkcs7_delete_crt (gnutls_pkcs7_t pkcs7, int indx) | ||
668 | { | ||
669 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
670 | int result; | ||
671 | char root2[MAX_NAME_SIZE]; | ||
672 | |||
673 | if (pkcs7 == NULL) | ||
674 | return GNUTLS_E_INVALID_REQUEST; | ||
675 | |||
676 | /* Step 1. Decode the signed data. | ||
677 | */ | ||
678 | result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL); | ||
679 | if (result < 0) | ||
680 | { | ||
681 | gnutls_assert (); | ||
682 | return result; | ||
683 | } | ||
684 | |||
685 | /* Step 2. Delete the certificate. | ||
686 | */ | ||
687 | |||
688 | snprintf (root2, sizeof (root2), "certificates.?%u", indx + 1); | ||
689 | |||
690 | result = asn1_write_value (c2, root2, NULL, 0); | ||
691 | if (result != ASN1_SUCCESS) | ||
692 | { | ||
693 | gnutls_assert (); | ||
694 | result = _gnutls_asn2err (result); | ||
695 | goto cleanup; | ||
696 | } | ||
697 | |||
698 | /* Step 3. Replace the old content with the new | ||
699 | */ | ||
700 | result = | ||
701 | _gnutls_x509_der_encode_and_copy (c2, "", pkcs7->pkcs7, "content", 0); | ||
702 | if (result < 0) | ||
703 | { | ||
704 | gnutls_assert (); | ||
705 | goto cleanup; | ||
706 | } | ||
707 | |||
708 | asn1_delete_structure (&c2); | ||
709 | |||
710 | return 0; | ||
711 | |||
712 | cleanup: | ||
713 | if (c2) | ||
714 | asn1_delete_structure (&c2); | ||
715 | return result; | ||
716 | } | ||
717 | |||
718 | /* Read and write CRLs | ||
719 | */ | ||
720 | |||
721 | /** | ||
722 | * gnutls_pkcs7_get_crl_raw - This function returns a crl in a PKCS7 crl set | ||
723 | * @pkcs7_struct: should contain a gnutls_pkcs7_t structure | ||
724 | * @indx: contains the index of the crl to extract | ||
725 | * @crl: the contents of the crl will be copied there (may be null) | ||
726 | * @crl_size: should hold the size of the crl | ||
727 | * | ||
728 | * This function will return a crl of the PKCS7 or RFC2630 crl set. | ||
729 | * Returns 0 on success. If the provided buffer is not long enough, | ||
730 | * then @crl_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER is returned. | ||
731 | * | ||
732 | * After the last crl has been read GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE | ||
733 | * will be returned. | ||
734 | * | ||
735 | **/ | ||
736 | int | ||
737 | gnutls_pkcs7_get_crl_raw (gnutls_pkcs7_t pkcs7, | ||
738 | int indx, void *crl, size_t * crl_size) | ||
739 | { | ||
740 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
741 | int result; | ||
742 | char root2[MAX_NAME_SIZE]; | ||
743 | gnutls_datum_t tmp = { NULL, 0 }; | ||
744 | int start, end; | ||
745 | |||
746 | if (pkcs7 == NULL || crl_size == NULL) | ||
747 | return GNUTLS_E_INVALID_REQUEST; | ||
748 | |||
749 | /* Step 1. decode the signed data. | ||
750 | */ | ||
751 | result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, &tmp); | ||
752 | if (result < 0) | ||
753 | { | ||
754 | gnutls_assert (); | ||
755 | return result; | ||
756 | } | ||
757 | |||
758 | /* Step 2. Parse the CertificateSet | ||
759 | */ | ||
760 | |||
761 | snprintf (root2, sizeof (root2), "crls.?%u", indx + 1); | ||
762 | |||
763 | /* Get the raw CRL | ||
764 | */ | ||
765 | result = asn1_der_decoding_startEnd (c2, tmp.data, tmp.size, | ||
766 | root2, &start, &end); | ||
767 | |||
768 | if (result != ASN1_SUCCESS) | ||
769 | { | ||
770 | gnutls_assert (); | ||
771 | result = _gnutls_asn2err (result); | ||
772 | goto cleanup; | ||
773 | } | ||
774 | |||
775 | end = end - start + 1; | ||
776 | |||
777 | if ((unsigned) end > *crl_size) | ||
778 | { | ||
779 | *crl_size = end; | ||
780 | result = GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
781 | goto cleanup; | ||
782 | } | ||
783 | |||
784 | if (crl) | ||
785 | memcpy (crl, &tmp.data[start], end); | ||
786 | |||
787 | *crl_size = end; | ||
788 | |||
789 | result = 0; | ||
790 | |||
791 | cleanup: | ||
792 | _gnutls_free_datum (&tmp); | ||
793 | if (c2) | ||
794 | asn1_delete_structure (&c2); | ||
795 | return result; | ||
796 | } | ||
797 | |||
798 | /** | ||
799 | * gnutls_pkcs7_get_crl_count - This function returns the number of crls in a PKCS7 crl set | ||
800 | * @pkcs7_struct: should contain a gnutls_pkcs7_t structure | ||
801 | * | ||
802 | * This function will return the number of certifcates in the PKCS7 or | ||
803 | * RFC2630 crl set. | ||
804 | * | ||
805 | * Returns a negative value on failure. | ||
806 | * | ||
807 | **/ | ||
808 | int | ||
809 | gnutls_pkcs7_get_crl_count (gnutls_pkcs7_t pkcs7) | ||
810 | { | ||
811 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
812 | int result, count; | ||
813 | |||
814 | if (pkcs7 == NULL) | ||
815 | return GNUTLS_E_INVALID_REQUEST; | ||
816 | |||
817 | /* Step 1. decode the signed data. | ||
818 | */ | ||
819 | result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL); | ||
820 | if (result < 0) | ||
821 | { | ||
822 | gnutls_assert (); | ||
823 | return result; | ||
824 | } | ||
825 | |||
826 | /* Step 2. Count the CertificateSet */ | ||
827 | |||
828 | result = asn1_number_of_elements (c2, "crls", &count); | ||
829 | |||
830 | asn1_delete_structure (&c2); | ||
831 | |||
832 | if (result != ASN1_SUCCESS) | ||
833 | { | ||
834 | gnutls_assert (); | ||
835 | return 0; /* no crls */ | ||
836 | } | ||
837 | |||
838 | return count; | ||
839 | |||
840 | } | ||
841 | |||
842 | /** | ||
843 | * gnutls_pkcs7_set_crl_raw - This function adds a crl in a PKCS7 crl set | ||
844 | * @pkcs7_struct: should contain a gnutls_pkcs7_t structure | ||
845 | * @crl: the DER encoded crl to be added | ||
846 | * | ||
847 | * This function will add a crl to the PKCS7 or RFC2630 crl set. | ||
848 | * Returns 0 on success. | ||
849 | * | ||
850 | **/ | ||
851 | int | ||
852 | gnutls_pkcs7_set_crl_raw (gnutls_pkcs7_t pkcs7, const gnutls_datum_t * crl) | ||
853 | { | ||
854 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
855 | int result; | ||
856 | |||
857 | if (pkcs7 == NULL) | ||
858 | return GNUTLS_E_INVALID_REQUEST; | ||
859 | |||
860 | /* Step 1. decode the signed data. | ||
861 | */ | ||
862 | result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL); | ||
863 | if (result < 0 && result != GNUTLS_E_ASN1_VALUE_NOT_FOUND) | ||
864 | { | ||
865 | gnutls_assert (); | ||
866 | return result; | ||
867 | } | ||
868 | |||
869 | /* If the signed data are uninitialized | ||
870 | * then create them. | ||
871 | */ | ||
872 | if (result == GNUTLS_E_ASN1_VALUE_NOT_FOUND) | ||
873 | { | ||
874 | /* The pkcs7 structure is new, so create the | ||
875 | * signedData. | ||
876 | */ | ||
877 | result = create_empty_signed_data (pkcs7->pkcs7, &c2); | ||
878 | if (result < 0) | ||
879 | { | ||
880 | gnutls_assert (); | ||
881 | return result; | ||
882 | } | ||
883 | } | ||
884 | |||
885 | /* Step 2. Append the new crl. | ||
886 | */ | ||
887 | |||
888 | result = asn1_write_value (c2, "crls", "NEW", 1); | ||
889 | if (result != ASN1_SUCCESS) | ||
890 | { | ||
891 | gnutls_assert (); | ||
892 | result = _gnutls_asn2err (result); | ||
893 | goto cleanup; | ||
894 | } | ||
895 | |||
896 | result = asn1_write_value (c2, "crls.?LAST", crl->data, crl->size); | ||
897 | if (result != ASN1_SUCCESS) | ||
898 | { | ||
899 | gnutls_assert (); | ||
900 | result = _gnutls_asn2err (result); | ||
901 | goto cleanup; | ||
902 | } | ||
903 | |||
904 | /* Step 3. Replace the old content with the new | ||
905 | */ | ||
906 | result = | ||
907 | _gnutls_x509_der_encode_and_copy (c2, "", pkcs7->pkcs7, "content", 0); | ||
908 | if (result < 0) | ||
909 | { | ||
910 | gnutls_assert (); | ||
911 | goto cleanup; | ||
912 | } | ||
913 | |||
914 | asn1_delete_structure (&c2); | ||
915 | |||
916 | return 0; | ||
917 | |||
918 | cleanup: | ||
919 | if (c2) | ||
920 | asn1_delete_structure (&c2); | ||
921 | return result; | ||
922 | } | ||
923 | |||
924 | /** | ||
925 | * gnutls_pkcs7_set_crl - This function adds a parsed crl in a PKCS7 crl set | ||
926 | * @pkcs7_struct: should contain a gnutls_pkcs7_t structure | ||
927 | * @crl: the DER encoded crl to be added | ||
928 | * | ||
929 | * This function will add a parsed crl to the PKCS7 or RFC2630 crl set. | ||
930 | * Returns 0 on success. | ||
931 | * | ||
932 | **/ | ||
933 | int | ||
934 | gnutls_pkcs7_set_crl (gnutls_pkcs7_t pkcs7, gnutls_x509_crl_t crl) | ||
935 | { | ||
936 | int ret; | ||
937 | gnutls_datum_t data; | ||
938 | |||
939 | if (pkcs7 == NULL) | ||
940 | return GNUTLS_E_INVALID_REQUEST; | ||
941 | |||
942 | ret = _gnutls_x509_der_encode (crl->crl, "", &data, 0); | ||
943 | if (ret < 0) | ||
944 | { | ||
945 | gnutls_assert (); | ||
946 | return ret; | ||
947 | } | ||
948 | |||
949 | ret = gnutls_pkcs7_set_crl_raw (pkcs7, &data); | ||
950 | |||
951 | _gnutls_free_datum (&data); | ||
952 | |||
953 | if (ret < 0) | ||
954 | { | ||
955 | gnutls_assert (); | ||
956 | return ret; | ||
957 | } | ||
958 | |||
959 | return 0; | ||
960 | } | ||
961 | |||
962 | /** | ||
963 | * gnutls_pkcs7_delete_crl - This function deletes a crl from a PKCS7 crl set | ||
964 | * @pkcs7_struct: should contain a gnutls_pkcs7_t structure | ||
965 | * @indx: the index of the crl to delete | ||
966 | * | ||
967 | * This function will delete a crl from a PKCS7 or RFC2630 crl set. | ||
968 | * Index starts from 0. Returns 0 on success. | ||
969 | * | ||
970 | **/ | ||
971 | int | ||
972 | gnutls_pkcs7_delete_crl (gnutls_pkcs7_t pkcs7, int indx) | ||
973 | { | ||
974 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
975 | int result; | ||
976 | char root2[MAX_NAME_SIZE]; | ||
977 | |||
978 | if (pkcs7 == NULL) | ||
979 | return GNUTLS_E_INVALID_REQUEST; | ||
980 | |||
981 | /* Step 1. Decode the signed data. | ||
982 | */ | ||
983 | result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL); | ||
984 | if (result < 0) | ||
985 | { | ||
986 | gnutls_assert (); | ||
987 | return result; | ||
988 | } | ||
989 | |||
990 | /* Step 2. Delete the crl. | ||
991 | */ | ||
992 | |||
993 | snprintf (root2, sizeof (root2), "crls.?%u", indx + 1); | ||
994 | |||
995 | result = asn1_write_value (c2, root2, NULL, 0); | ||
996 | if (result != ASN1_SUCCESS) | ||
997 | { | ||
998 | gnutls_assert (); | ||
999 | result = _gnutls_asn2err (result); | ||
1000 | goto cleanup; | ||
1001 | } | ||
1002 | |||
1003 | /* Step 3. Replace the old content with the new | ||
1004 | */ | ||
1005 | result = | ||
1006 | _gnutls_x509_der_encode_and_copy (c2, "", pkcs7->pkcs7, "content", 0); | ||
1007 | if (result < 0) | ||
1008 | { | ||
1009 | gnutls_assert (); | ||
1010 | goto cleanup; | ||
1011 | } | ||
1012 | |||
1013 | asn1_delete_structure (&c2); | ||
1014 | |||
1015 | return 0; | ||
1016 | |||
1017 | cleanup: | ||
1018 | if (c2) | ||
1019 | asn1_delete_structure (&c2); | ||
1020 | return result; | ||
1021 | } | ||
1022 | |||
1023 | #endif /* ENABLE_PKI */ | ||
diff --git a/src/daemon/https/x509/pkcs7.h b/src/daemon/https/x509/pkcs7.h new file mode 100644 index 00000000..ee1990c3 --- /dev/null +++ b/src/daemon/https/x509/pkcs7.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include "x509.h" | ||
26 | |||
27 | typedef struct gnutls_pkcs7_int | ||
28 | { | ||
29 | ASN1_TYPE pkcs7; | ||
30 | } gnutls_pkcs7_int; | ||
diff --git a/src/daemon/https/x509/privkey.h b/src/daemon/https/x509/privkey.h new file mode 100644 index 00000000..6e645b9d --- /dev/null +++ b/src/daemon/https/x509/privkey.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include "x509.h" | ||
26 | |||
27 | ASN1_TYPE _gnutls_privkey_decode_pkcs1_rsa_key (const gnutls_datum_t * | ||
28 | raw_key, | ||
29 | gnutls_x509_privkey_t pkey); | ||
30 | |||
31 | int _gnutls_asn1_encode_dsa (ASN1_TYPE * c2, mpi_t * params); | ||
diff --git a/src/daemon/https/x509/privkey_pkcs8.c b/src/daemon/https/x509/privkey_pkcs8.c new file mode 100644 index 00000000..2f1921bb --- /dev/null +++ b/src/daemon/https/x509/privkey_pkcs8.c | |||
@@ -0,0 +1,2219 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <gnutls_int.h> | ||
26 | |||
27 | #ifdef ENABLE_PKI | ||
28 | |||
29 | #include <gnutls_datum.h> | ||
30 | #include <gnutls_global.h> | ||
31 | #include <gnutls_errors.h> | ||
32 | #include <gnutls_rsa_export.h> | ||
33 | #include <common.h> | ||
34 | #include <gnutls_x509.h> | ||
35 | #include <x509_b64.h> | ||
36 | #include <x509.h> | ||
37 | #include <dn.h> | ||
38 | #include <pkcs12.h> | ||
39 | #include <privkey.h> | ||
40 | #include <extensions.h> | ||
41 | #include <mpi.h> | ||
42 | #include <gnutls_algorithms.h> | ||
43 | #include <gnutls_num.h> | ||
44 | #include "gc.h" | ||
45 | |||
46 | #define PBES2_OID "1.2.840.113549.1.5.13" | ||
47 | #define PBKDF2_OID "1.2.840.113549.1.5.12" | ||
48 | #define DES_EDE3_CBC_OID "1.2.840.113549.3.7" | ||
49 | #define DES_CBC_OID "1.3.14.3.2.7" | ||
50 | |||
51 | /* oid_pbeWithSHAAnd3_KeyTripleDES_CBC */ | ||
52 | #define PKCS12_PBE_3DES_SHA1_OID "1.2.840.113549.1.12.1.3" | ||
53 | #define PKCS12_PBE_ARCFOUR_SHA1_OID "1.2.840.113549.1.12.1.1" | ||
54 | #define PKCS12_PBE_RC2_40_SHA1_OID "1.2.840.113549.1.12.1.6" | ||
55 | |||
56 | struct pbkdf2_params | ||
57 | { | ||
58 | opaque salt[32]; | ||
59 | int salt_size; | ||
60 | unsigned int iter_count; | ||
61 | unsigned int key_size; | ||
62 | }; | ||
63 | |||
64 | struct pbe_enc_params | ||
65 | { | ||
66 | gnutls_cipher_algorithm_t cipher; | ||
67 | opaque iv[8]; | ||
68 | int iv_size; | ||
69 | }; | ||
70 | |||
71 | static int generate_key (schema_id schema, const char *password, | ||
72 | struct pbkdf2_params *kdf_params, | ||
73 | struct pbe_enc_params *enc_params, | ||
74 | gnutls_datum_t * key); | ||
75 | static int read_pbkdf2_params (ASN1_TYPE pbes2_asn, | ||
76 | const gnutls_datum_t * der, | ||
77 | struct pbkdf2_params *params); | ||
78 | static int read_pbe_enc_params (ASN1_TYPE pbes2_asn, | ||
79 | const gnutls_datum_t * der, | ||
80 | struct pbe_enc_params *params); | ||
81 | static int decrypt_data (schema_id, ASN1_TYPE pkcs8_asn, const char *root, | ||
82 | const char *password, | ||
83 | const struct pbkdf2_params *kdf_params, | ||
84 | const struct pbe_enc_params *enc_params, | ||
85 | gnutls_datum_t * decrypted_data); | ||
86 | static int decode_private_key_info (const gnutls_datum_t * der, | ||
87 | gnutls_x509_privkey_t pkey); | ||
88 | static int write_schema_params (schema_id schema, ASN1_TYPE pkcs8_asn, | ||
89 | const char *where, | ||
90 | const struct pbkdf2_params *kdf_params, | ||
91 | const struct pbe_enc_params *enc_params); | ||
92 | static int encrypt_data (const gnutls_datum_t * plain, | ||
93 | const struct pbe_enc_params *enc_params, | ||
94 | gnutls_datum_t * key, gnutls_datum_t * encrypted); | ||
95 | |||
96 | static int read_pkcs12_kdf_params (ASN1_TYPE pbes2_asn, | ||
97 | struct pbkdf2_params *params); | ||
98 | static int write_pkcs12_kdf_params (ASN1_TYPE pbes2_asn, | ||
99 | const struct pbkdf2_params *params); | ||
100 | |||
101 | #define PEM_PKCS8 "ENCRYPTED PRIVATE KEY" | ||
102 | #define PEM_UNENCRYPTED_PKCS8 "PRIVATE KEY" | ||
103 | |||
104 | /* Returns a negative error code if the encryption schema in | ||
105 | * the OID is not supported. The schema ID is returned. | ||
106 | */ | ||
107 | inline static int | ||
108 | check_schema (const char *oid) | ||
109 | { | ||
110 | |||
111 | if (strcmp (oid, PBES2_OID) == 0) | ||
112 | return PBES2; | ||
113 | |||
114 | if (strcmp (oid, PKCS12_PBE_3DES_SHA1_OID) == 0) | ||
115 | return PKCS12_3DES_SHA1; | ||
116 | |||
117 | if (strcmp (oid, PKCS12_PBE_ARCFOUR_SHA1_OID) == 0) | ||
118 | return PKCS12_ARCFOUR_SHA1; | ||
119 | |||
120 | if (strcmp (oid, PKCS12_PBE_RC2_40_SHA1_OID) == 0) | ||
121 | return PKCS12_RC2_40_SHA1; | ||
122 | |||
123 | _gnutls_x509_log ("PKCS encryption schema OID '%s' is unsupported.\n", oid); | ||
124 | |||
125 | return GNUTLS_E_UNKNOWN_CIPHER_TYPE; | ||
126 | } | ||
127 | |||
128 | /* Encodes a private key to the raw format PKCS #8 needs. | ||
129 | * For RSA it is a PKCS #1 DER private key and for DSA it is | ||
130 | * an ASN.1 INTEGER of the x value. | ||
131 | */ | ||
132 | inline static int | ||
133 | _encode_privkey (gnutls_x509_privkey pkey, gnutls_datum * raw) | ||
134 | { | ||
135 | size_t size = 0; | ||
136 | opaque *data = NULL; | ||
137 | int ret; | ||
138 | ASN1_TYPE spk = ASN1_TYPE_EMPTY; | ||
139 | |||
140 | switch (pkey->pk_algorithm) | ||
141 | { | ||
142 | case GNUTLS_PK_RSA: | ||
143 | ret = | ||
144 | gnutls_x509_privkey_export (pkey, GNUTLS_X509_FMT_DER, NULL, &size); | ||
145 | if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) | ||
146 | { | ||
147 | gnutls_assert (); | ||
148 | goto error; | ||
149 | } | ||
150 | |||
151 | data = gnutls_malloc (size); | ||
152 | if (data == NULL) | ||
153 | { | ||
154 | gnutls_assert (); | ||
155 | ret = GNUTLS_E_MEMORY_ERROR; | ||
156 | goto error; | ||
157 | } | ||
158 | |||
159 | ret = | ||
160 | gnutls_x509_privkey_export (pkey, GNUTLS_X509_FMT_DER, data, &size); | ||
161 | if (ret < 0) | ||
162 | { | ||
163 | gnutls_assert (); | ||
164 | goto error; | ||
165 | } | ||
166 | |||
167 | raw->data = data; | ||
168 | raw->size = size; | ||
169 | break; | ||
170 | default: | ||
171 | gnutls_assert (); | ||
172 | return GNUTLS_E_INVALID_REQUEST; | ||
173 | } | ||
174 | |||
175 | return 0; | ||
176 | |||
177 | error: | ||
178 | gnutls_free (data); | ||
179 | asn1_delete_structure (&spk); | ||
180 | return ret; | ||
181 | |||
182 | } | ||
183 | |||
184 | /* | ||
185 | * Encodes a PKCS #1 private key to a PKCS #8 private key | ||
186 | * info. The output will be allocated and stored into der. Also | ||
187 | * the ASN1_TYPE of private key info will be returned. | ||
188 | */ | ||
189 | static int | ||
190 | encode_to_private_key_info (gnutls_x509_privkey_t pkey, | ||
191 | gnutls_datum_t * der, ASN1_TYPE * pkey_info) | ||
192 | { | ||
193 | int result, len; | ||
194 | opaque null = 0; | ||
195 | const char *oid; | ||
196 | gnutls_datum algo_params = | ||
197 | { NULL, 0}; | ||
198 | gnutls_datum algo_privkey = | ||
199 | { NULL, 0}; | ||
200 | |||
201 | if (pkey->pk_algorithm == GNUTLS_PK_RSA) | ||
202 | { | ||
203 | oid = PK_PKIX1_RSA_OID; | ||
204 | /* parameters are null | ||
205 | */ | ||
206 | } | ||
207 | else | ||
208 | { | ||
209 | oid = PK_DSA_OID; | ||
210 | result = | ||
211 | _gnutls_x509_write_dsa_params (pkey->params, pkey->params_size, | ||
212 | &algo_params); | ||
213 | if (result < 0) | ||
214 | { | ||
215 | gnutls_assert (); | ||
216 | return result; | ||
217 | } | ||
218 | } | ||
219 | |||
220 | if ((result = | ||
221 | asn1_create_element (_gnutls_get_pkix (), | ||
222 | "PKIX1.pkcs-8-PrivateKeyInfo", | ||
223 | pkey_info)) != ASN1_SUCCESS) | ||
224 | { | ||
225 | gnutls_assert (); | ||
226 | result = _gnutls_asn2err (result); | ||
227 | goto error; | ||
228 | } | ||
229 | |||
230 | /* Write the version. | ||
231 | */ | ||
232 | result = asn1_write_value (*pkey_info, "version", &null, 1); | ||
233 | if (result != ASN1_SUCCESS) | ||
234 | { | ||
235 | gnutls_assert (); | ||
236 | result = _gnutls_asn2err (result); | ||
237 | goto error; | ||
238 | } | ||
239 | |||
240 | /* write the privateKeyAlgorithm | ||
241 | * fields. (OID+NULL data) | ||
242 | */ | ||
243 | result = | ||
244 | asn1_write_value (*pkey_info, "privateKeyAlgorithm.algorithm", oid, 1); | ||
245 | if (result != ASN1_SUCCESS) | ||
246 | { | ||
247 | gnutls_assert (); | ||
248 | result = _gnutls_asn2err (result); | ||
249 | goto error; | ||
250 | } | ||
251 | |||
252 | result = | ||
253 | asn1_write_value (*pkey_info, "privateKeyAlgorithm.parameters", | ||
254 | algo_params.data, algo_params.size); | ||
255 | _gnutls_free_datum (&algo_params); | ||
256 | if (result != ASN1_SUCCESS) | ||
257 | { | ||
258 | gnutls_assert (); | ||
259 | result = _gnutls_asn2err (result); | ||
260 | goto error; | ||
261 | } | ||
262 | |||
263 | /* Write the raw private key | ||
264 | */ | ||
265 | result = _encode_privkey (pkey, &algo_privkey); | ||
266 | if (result < 0) | ||
267 | { | ||
268 | gnutls_assert (); | ||
269 | goto error; | ||
270 | } | ||
271 | |||
272 | result = | ||
273 | asn1_write_value (*pkey_info, "privateKey", algo_privkey.data, | ||
274 | algo_privkey.size); | ||
275 | _gnutls_free_datum (&algo_privkey); | ||
276 | |||
277 | if (result != ASN1_SUCCESS) | ||
278 | { | ||
279 | gnutls_assert (); | ||
280 | result = _gnutls_asn2err (result); | ||
281 | goto error; | ||
282 | } | ||
283 | |||
284 | /* Append an empty Attributes field. | ||
285 | */ | ||
286 | result = asn1_write_value (*pkey_info, "attributes", NULL, 0); | ||
287 | if (result != ASN1_SUCCESS) | ||
288 | { | ||
289 | gnutls_assert (); | ||
290 | result = _gnutls_asn2err (result); | ||
291 | goto error; | ||
292 | } | ||
293 | |||
294 | /* DER Encode the generated private key info. | ||
295 | */ | ||
296 | len = 0; | ||
297 | result = asn1_der_coding (*pkey_info, "", NULL, &len, NULL); | ||
298 | if (result != ASN1_MEM_ERROR) | ||
299 | { | ||
300 | gnutls_assert (); | ||
301 | result = _gnutls_asn2err (result); | ||
302 | goto error; | ||
303 | } | ||
304 | |||
305 | /* allocate data for the der | ||
306 | */ | ||
307 | der->size = len; | ||
308 | der->data = gnutls_malloc (len); | ||
309 | if (der->data == NULL) | ||
310 | { | ||
311 | gnutls_assert (); | ||
312 | return GNUTLS_E_MEMORY_ERROR; | ||
313 | } | ||
314 | |||
315 | result = asn1_der_coding (*pkey_info, "", der->data, &len, NULL); | ||
316 | if (result != ASN1_SUCCESS) | ||
317 | { | ||
318 | gnutls_assert (); | ||
319 | result = _gnutls_asn2err (result); | ||
320 | goto error; | ||
321 | } | ||
322 | |||
323 | return 0; | ||
324 | |||
325 | error: | ||
326 | asn1_delete_structure (pkey_info); | ||
327 | _gnutls_free_datum (&algo_params); | ||
328 | _gnutls_free_datum (&algo_privkey); | ||
329 | return result; | ||
330 | |||
331 | } | ||
332 | |||
333 | /* Converts a PKCS #8 private key info to | ||
334 | * a PKCS #8 EncryptedPrivateKeyInfo. | ||
335 | */ | ||
336 | static int | ||
337 | encode_to_pkcs8_key (schema_id schema, const gnutls_datum_t * der_key, | ||
338 | const char *password, ASN1_TYPE * out) | ||
339 | { | ||
340 | int result; | ||
341 | gnutls_datum_t key = | ||
342 | { NULL, 0}; | ||
343 | gnutls_datum_t tmp = | ||
344 | { NULL, 0}; | ||
345 | ASN1_TYPE pkcs8_asn = ASN1_TYPE_EMPTY; | ||
346 | struct pbkdf2_params kdf_params; | ||
347 | struct pbe_enc_params enc_params; | ||
348 | |||
349 | if ((result = | ||
350 | asn1_create_element (_gnutls_get_pkix (), | ||
351 | "PKIX1.pkcs-8-EncryptedPrivateKeyInfo", | ||
352 | &pkcs8_asn)) != ASN1_SUCCESS) | ||
353 | { | ||
354 | gnutls_assert (); | ||
355 | result = _gnutls_asn2err (result); | ||
356 | goto error; | ||
357 | } | ||
358 | |||
359 | /* Write the encryption schema OID | ||
360 | */ | ||
361 | switch (schema) | ||
362 | { | ||
363 | case PBES2: | ||
364 | result = | ||
365 | asn1_write_value (pkcs8_asn, "encryptionAlgorithm.algorithm", | ||
366 | PBES2_OID, 1); | ||
367 | break; | ||
368 | case PKCS12_3DES_SHA1: | ||
369 | result = | ||
370 | asn1_write_value (pkcs8_asn, "encryptionAlgorithm.algorithm", | ||
371 | PKCS12_PBE_3DES_SHA1_OID, 1); | ||
372 | break; | ||
373 | case PKCS12_ARCFOUR_SHA1: | ||
374 | result = | ||
375 | asn1_write_value (pkcs8_asn, "encryptionAlgorithm.algorithm", | ||
376 | PKCS12_PBE_ARCFOUR_SHA1_OID, 1); | ||
377 | break; | ||
378 | case PKCS12_RC2_40_SHA1: | ||
379 | result = | ||
380 | asn1_write_value (pkcs8_asn, "encryptionAlgorithm.algorithm", | ||
381 | PKCS12_PBE_RC2_40_SHA1_OID, 1); | ||
382 | break; | ||
383 | |||
384 | } | ||
385 | |||
386 | if (result != ASN1_SUCCESS) | ||
387 | { | ||
388 | gnutls_assert (); | ||
389 | result = _gnutls_asn2err (result); | ||
390 | goto error; | ||
391 | } | ||
392 | |||
393 | /* Generate a symmetric key. | ||
394 | */ | ||
395 | |||
396 | result = generate_key (schema, password, &kdf_params, &enc_params, &key); | ||
397 | if (result < 0) | ||
398 | { | ||
399 | gnutls_assert (); | ||
400 | goto error; | ||
401 | } | ||
402 | |||
403 | result = | ||
404 | write_schema_params (schema, pkcs8_asn, | ||
405 | "encryptionAlgorithm.parameters", &kdf_params, | ||
406 | &enc_params); | ||
407 | if (result < 0) | ||
408 | { | ||
409 | gnutls_assert (); | ||
410 | goto error; | ||
411 | } | ||
412 | |||
413 | /* Parameters have been encoded. Now | ||
414 | * encrypt the Data. | ||
415 | */ | ||
416 | result = encrypt_data (der_key, &enc_params, &key, &tmp); | ||
417 | if (result < 0) | ||
418 | { | ||
419 | gnutls_assert (); | ||
420 | goto error; | ||
421 | } | ||
422 | |||
423 | /* write the encrypted data. | ||
424 | */ | ||
425 | result = asn1_write_value (pkcs8_asn, "encryptedData", tmp.data, tmp.size); | ||
426 | if (result != ASN1_SUCCESS) | ||
427 | { | ||
428 | gnutls_assert (); | ||
429 | result = _gnutls_asn2err (result); | ||
430 | goto error; | ||
431 | } | ||
432 | |||
433 | _gnutls_free_datum (&tmp); | ||
434 | _gnutls_free_datum (&key); | ||
435 | |||
436 | *out = pkcs8_asn; | ||
437 | |||
438 | return 0; | ||
439 | |||
440 | error: | ||
441 | _gnutls_free_datum (&key); | ||
442 | _gnutls_free_datum (&tmp); | ||
443 | asn1_delete_structure (&pkcs8_asn); | ||
444 | return result; | ||
445 | } | ||
446 | |||
447 | /** | ||
448 | * gnutls_x509_privkey_export_pkcs8 - This function will export the private key to PKCS8 format | ||
449 | * @key: Holds the key | ||
450 | * @format: the format of output params. One of PEM or DER. | ||
451 | * @password: the password that will be used to encrypt the key. | ||
452 | * @flags: an ORed sequence of gnutls_pkcs_encrypt_flags_t | ||
453 | * @output_data: will contain a private key PEM or DER encoded | ||
454 | * @output_data_size: holds the size of output_data (and will be | ||
455 | * replaced by the actual size of parameters) | ||
456 | * | ||
457 | * This function will export the private key to a PKCS8 structure. | ||
458 | * Both RSA and DSA keys can be exported. For DSA keys we use | ||
459 | * PKCS #11 definitions. If the flags do not specify the encryption | ||
460 | * cipher, then the default 3DES (PBES2) will be used. | ||
461 | * | ||
462 | * The @password can be either ASCII or UTF-8 in the default PBES2 | ||
463 | * encryption schemas, or ASCII for the PKCS12 schemas. | ||
464 | * | ||
465 | * If the buffer provided is not long enough to hold the output, then | ||
466 | * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will | ||
467 | * be returned. | ||
468 | * | ||
469 | * If the structure is PEM encoded, it will have a header | ||
470 | * of "BEGIN ENCRYPTED PRIVATE KEY" or "BEGIN PRIVATE KEY" if | ||
471 | * encryption is not used. | ||
472 | * | ||
473 | * Return value: In case of failure a negative value will be | ||
474 | * returned, and 0 on success. | ||
475 | * | ||
476 | **/ | ||
477 | int | ||
478 | gnutls_x509_privkey_export_pkcs8 (gnutls_x509_privkey_t key, | ||
479 | gnutls_x509_crt_fmt_t format, | ||
480 | const char *password, | ||
481 | unsigned int flags, | ||
482 | void *output_data, | ||
483 | size_t * output_data_size) | ||
484 | { | ||
485 | ASN1_TYPE pkcs8_asn, pkey_info; | ||
486 | int ret; | ||
487 | gnutls_datum_t tmp; | ||
488 | schema_id schema; | ||
489 | |||
490 | if (key == NULL) | ||
491 | { | ||
492 | gnutls_assert (); | ||
493 | return GNUTLS_E_INVALID_REQUEST; | ||
494 | } | ||
495 | |||
496 | /* Get the private key info | ||
497 | * tmp holds the DER encoding. | ||
498 | */ | ||
499 | ret = encode_to_private_key_info (key, &tmp, &pkey_info); | ||
500 | if (ret < 0) | ||
501 | { | ||
502 | gnutls_assert (); | ||
503 | return ret; | ||
504 | } | ||
505 | |||
506 | if (flags & GNUTLS_PKCS_USE_PKCS12_3DES) | ||
507 | schema = PKCS12_3DES_SHA1; | ||
508 | else if (flags & GNUTLS_PKCS_USE_PKCS12_ARCFOUR) | ||
509 | schema = PKCS12_ARCFOUR_SHA1; | ||
510 | else if (flags & GNUTLS_PKCS_USE_PKCS12_RC2_40) | ||
511 | schema = PKCS12_RC2_40_SHA1; | ||
512 | else | ||
513 | schema = PBES2; | ||
514 | |||
515 | if ((flags & GNUTLS_PKCS_PLAIN) || password == NULL) | ||
516 | { | ||
517 | _gnutls_free_datum (&tmp); | ||
518 | |||
519 | ret = | ||
520 | _gnutls_x509_export_int (pkey_info, format, | ||
521 | PEM_UNENCRYPTED_PKCS8, | ||
522 | output_data, output_data_size); | ||
523 | |||
524 | asn1_delete_structure (&pkey_info); | ||
525 | } | ||
526 | else | ||
527 | { | ||
528 | asn1_delete_structure (&pkey_info); /* we don't need it */ | ||
529 | |||
530 | ret = encode_to_pkcs8_key (schema, &tmp, password, &pkcs8_asn); | ||
531 | _gnutls_free_datum (&tmp); | ||
532 | |||
533 | if (ret < 0) | ||
534 | { | ||
535 | gnutls_assert (); | ||
536 | return ret; | ||
537 | } | ||
538 | |||
539 | ret = | ||
540 | _gnutls_x509_export_int (pkcs8_asn, format, PEM_PKCS8, | ||
541 | output_data, output_data_size); | ||
542 | |||
543 | asn1_delete_structure (&pkcs8_asn); | ||
544 | } | ||
545 | |||
546 | return ret; | ||
547 | } | ||
548 | |||
549 | /* Read the parameters cipher, IV, salt etc using the given | ||
550 | * schema ID. | ||
551 | */ | ||
552 | static int | ||
553 | read_pkcs_schema_params (schema_id schema, const char *password, | ||
554 | const opaque * data, int data_size, | ||
555 | struct pbkdf2_params *kdf_params, | ||
556 | struct pbe_enc_params *enc_params) | ||
557 | { | ||
558 | ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY; | ||
559 | int result; | ||
560 | gnutls_datum_t tmp; | ||
561 | |||
562 | switch (schema) | ||
563 | { | ||
564 | |||
565 | case PBES2: | ||
566 | |||
567 | /* Now check the key derivation and the encryption | ||
568 | * functions. | ||
569 | */ | ||
570 | if ((result = | ||
571 | asn1_create_element (_gnutls_get_pkix (), | ||
572 | "PKIX1.pkcs-5-PBES2-params", | ||
573 | &pbes2_asn)) != ASN1_SUCCESS) | ||
574 | { | ||
575 | gnutls_assert (); | ||
576 | result = _gnutls_asn2err (result); | ||
577 | goto error; | ||
578 | } | ||
579 | |||
580 | /* Decode the parameters. | ||
581 | */ | ||
582 | result = asn1_der_decoding (&pbes2_asn, data, data_size, NULL); | ||
583 | if (result != ASN1_SUCCESS) | ||
584 | { | ||
585 | gnutls_assert (); | ||
586 | result = _gnutls_asn2err (result); | ||
587 | goto error; | ||
588 | } | ||
589 | |||
590 | tmp.data = (opaque *) data; | ||
591 | tmp.size = data_size; | ||
592 | |||
593 | result = read_pbkdf2_params (pbes2_asn, &tmp, kdf_params); | ||
594 | if (result < 0) | ||
595 | { | ||
596 | gnutls_assert (); | ||
597 | result = _gnutls_asn2err (result); | ||
598 | goto error; | ||
599 | } | ||
600 | |||
601 | result = read_pbe_enc_params (pbes2_asn, &tmp, enc_params); | ||
602 | if (result < 0) | ||
603 | { | ||
604 | gnutls_assert (); | ||
605 | result = _gnutls_asn2err (result); | ||
606 | goto error; | ||
607 | } | ||
608 | |||
609 | asn1_delete_structure (&pbes2_asn); | ||
610 | return 0; | ||
611 | break; | ||
612 | |||
613 | case PKCS12_3DES_SHA1: | ||
614 | case PKCS12_ARCFOUR_SHA1: | ||
615 | case PKCS12_RC2_40_SHA1: | ||
616 | |||
617 | if ((schema) == PKCS12_3DES_SHA1) | ||
618 | { | ||
619 | enc_params->cipher = GNUTLS_CIPHER_3DES_CBC; | ||
620 | enc_params->iv_size = 8; | ||
621 | } | ||
622 | else if ((schema) == PKCS12_ARCFOUR_SHA1) | ||
623 | { | ||
624 | enc_params->cipher = GNUTLS_CIPHER_ARCFOUR_128; | ||
625 | enc_params->iv_size = 0; | ||
626 | } | ||
627 | else if ((schema) == PKCS12_RC2_40_SHA1) | ||
628 | { | ||
629 | enc_params->cipher = GNUTLS_CIPHER_RC2_40_CBC; | ||
630 | enc_params->iv_size = 8; | ||
631 | } | ||
632 | |||
633 | if ((result = | ||
634 | asn1_create_element (_gnutls_get_pkix (), | ||
635 | "PKIX1.pkcs-12-PbeParams", | ||
636 | &pbes2_asn)) != ASN1_SUCCESS) | ||
637 | { | ||
638 | gnutls_assert (); | ||
639 | result = _gnutls_asn2err (result); | ||
640 | goto error; | ||
641 | } | ||
642 | |||
643 | /* Decode the parameters. | ||
644 | */ | ||
645 | result = asn1_der_decoding (&pbes2_asn, data, data_size, NULL); | ||
646 | if (result != ASN1_SUCCESS) | ||
647 | { | ||
648 | gnutls_assert (); | ||
649 | result = _gnutls_asn2err (result); | ||
650 | goto error; | ||
651 | } | ||
652 | |||
653 | result = read_pkcs12_kdf_params (pbes2_asn, kdf_params); | ||
654 | if (result < 0) | ||
655 | { | ||
656 | gnutls_assert (); | ||
657 | goto error; | ||
658 | } | ||
659 | |||
660 | if (enc_params->iv_size) | ||
661 | { | ||
662 | result = | ||
663 | _pkcs12_string_to_key (2 /*IV*/, kdf_params->salt, | ||
664 | kdf_params->salt_size, | ||
665 | kdf_params->iter_count, password, | ||
666 | enc_params->iv_size, enc_params->iv); | ||
667 | if (result < 0) | ||
668 | { | ||
669 | gnutls_assert (); | ||
670 | goto error; | ||
671 | } | ||
672 | |||
673 | } | ||
674 | |||
675 | asn1_delete_structure (&pbes2_asn); | ||
676 | |||
677 | return 0; | ||
678 | break; | ||
679 | |||
680 | } /* switch */ | ||
681 | |||
682 | return GNUTLS_E_UNKNOWN_CIPHER_TYPE; | ||
683 | |||
684 | error: | ||
685 | asn1_delete_structure (&pbes2_asn); | ||
686 | return result; | ||
687 | } | ||
688 | |||
689 | /* Converts a PKCS #8 key to | ||
690 | * an internal structure (gnutls_private_key) | ||
691 | * (normally a PKCS #1 encoded RSA key) | ||
692 | */ | ||
693 | static int | ||
694 | decode_pkcs8_key (const gnutls_datum_t * raw_key, | ||
695 | const char *password, gnutls_x509_privkey_t pkey) | ||
696 | { | ||
697 | int result, len; | ||
698 | char enc_oid[64]; | ||
699 | gnutls_datum_t tmp; | ||
700 | ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY, pkcs8_asn = ASN1_TYPE_EMPTY; | ||
701 | int params_start, params_end, params_len; | ||
702 | struct pbkdf2_params kdf_params; | ||
703 | struct pbe_enc_params enc_params; | ||
704 | schema_id schema; | ||
705 | |||
706 | if ((result = | ||
707 | asn1_create_element (_gnutls_get_pkix (), | ||
708 | "PKIX1.pkcs-8-EncryptedPrivateKeyInfo", | ||
709 | &pkcs8_asn)) != ASN1_SUCCESS) | ||
710 | { | ||
711 | gnutls_assert (); | ||
712 | result = _gnutls_asn2err (result); | ||
713 | goto error; | ||
714 | } | ||
715 | |||
716 | result = asn1_der_decoding (&pkcs8_asn, raw_key->data, raw_key->size, NULL); | ||
717 | if (result != ASN1_SUCCESS) | ||
718 | { | ||
719 | gnutls_assert (); | ||
720 | result = _gnutls_asn2err (result); | ||
721 | goto error; | ||
722 | } | ||
723 | |||
724 | /* Check the encryption schema OID | ||
725 | */ | ||
726 | len = sizeof (enc_oid); | ||
727 | result = | ||
728 | asn1_read_value (pkcs8_asn, "encryptionAlgorithm.algorithm", | ||
729 | enc_oid, &len); | ||
730 | if (result != ASN1_SUCCESS) | ||
731 | { | ||
732 | gnutls_assert (); | ||
733 | goto error; | ||
734 | } | ||
735 | |||
736 | if ((result = check_schema (enc_oid)) < 0) | ||
737 | { | ||
738 | gnutls_assert (); | ||
739 | goto error; | ||
740 | } | ||
741 | |||
742 | schema = result; | ||
743 | |||
744 | /* Get the DER encoding of the parameters. | ||
745 | */ | ||
746 | result = | ||
747 | asn1_der_decoding_startEnd (pkcs8_asn, raw_key->data, | ||
748 | raw_key->size, | ||
749 | "encryptionAlgorithm.parameters", | ||
750 | ¶ms_start, ¶ms_end); | ||
751 | if (result != ASN1_SUCCESS) | ||
752 | { | ||
753 | gnutls_assert (); | ||
754 | result = _gnutls_asn2err (result); | ||
755 | goto error; | ||
756 | } | ||
757 | params_len = params_end - params_start + 1; | ||
758 | |||
759 | result = | ||
760 | read_pkcs_schema_params (schema, password, | ||
761 | &raw_key->data[params_start], | ||
762 | params_len, &kdf_params, &enc_params); | ||
763 | |||
764 | /* Parameters have been decoded. Now | ||
765 | * decrypt the EncryptedData. | ||
766 | */ | ||
767 | result = | ||
768 | decrypt_data (schema, pkcs8_asn, "encryptedData", password, | ||
769 | &kdf_params, &enc_params, &tmp); | ||
770 | if (result < 0) | ||
771 | { | ||
772 | gnutls_assert (); | ||
773 | goto error; | ||
774 | } | ||
775 | |||
776 | asn1_delete_structure (&pkcs8_asn); | ||
777 | |||
778 | result = decode_private_key_info (&tmp, pkey); | ||
779 | _gnutls_free_datum (&tmp); | ||
780 | |||
781 | if (result < 0) | ||
782 | { | ||
783 | /* We've gotten this far. In the real world it's almost certain | ||
784 | * that we're dealing with a good file, but wrong password. | ||
785 | * Sadly like 90% of random data is somehow valid DER for the | ||
786 | * a first small number of bytes, so no easy way to guarantee. */ | ||
787 | if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND || | ||
788 | result == GNUTLS_E_ASN1_IDENTIFIER_NOT_FOUND || | ||
789 | result == GNUTLS_E_ASN1_DER_ERROR || | ||
790 | result == GNUTLS_E_ASN1_VALUE_NOT_FOUND || | ||
791 | result == GNUTLS_E_ASN1_GENERIC_ERROR || | ||
792 | result == GNUTLS_E_ASN1_VALUE_NOT_VALID || | ||
793 | result == GNUTLS_E_ASN1_TAG_ERROR || | ||
794 | result == GNUTLS_E_ASN1_TAG_IMPLICIT || | ||
795 | result == GNUTLS_E_ASN1_TYPE_ANY_ERROR || | ||
796 | result == GNUTLS_E_ASN1_SYNTAX_ERROR || | ||
797 | result == GNUTLS_E_ASN1_DER_OVERFLOW) | ||
798 | { | ||
799 | result = GNUTLS_E_DECRYPTION_FAILED; | ||
800 | } | ||
801 | |||
802 | gnutls_assert (); | ||
803 | goto error; | ||
804 | } | ||
805 | |||
806 | return 0; | ||
807 | |||
808 | error: | ||
809 | asn1_delete_structure (&pbes2_asn); | ||
810 | asn1_delete_structure (&pkcs8_asn); | ||
811 | return result; | ||
812 | } | ||
813 | |||
814 | /* Decodes an RSA privateKey from a PKCS8 structure. | ||
815 | */ | ||
816 | static int | ||
817 | _decode_pkcs8_rsa_key (ASN1_TYPE pkcs8_asn, gnutls_x509_privkey pkey) | ||
818 | { | ||
819 | int ret; | ||
820 | gnutls_datum tmp; | ||
821 | |||
822 | ret = _gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp, 0); | ||
823 | if (ret < 0) | ||
824 | { | ||
825 | gnutls_assert (); | ||
826 | goto error; | ||
827 | } | ||
828 | |||
829 | pkey->key = _gnutls_privkey_decode_pkcs1_rsa_key (&tmp, pkey); | ||
830 | _gnutls_free_datum (&tmp); | ||
831 | if (pkey->key == NULL) | ||
832 | { | ||
833 | gnutls_assert (); | ||
834 | goto error; | ||
835 | } | ||
836 | |||
837 | return 0; | ||
838 | |||
839 | error: | ||
840 | gnutls_x509_privkey_deinit (pkey); | ||
841 | return ret; | ||
842 | } | ||
843 | |||
844 | /* Decodes an DSA privateKey and params from a PKCS8 structure. | ||
845 | */ | ||
846 | static int | ||
847 | _decode_pkcs8_dsa_key (ASN1_TYPE pkcs8_asn, gnutls_x509_privkey pkey) | ||
848 | { | ||
849 | int ret; | ||
850 | gnutls_datum tmp; | ||
851 | |||
852 | ret = _gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp, 0); | ||
853 | if (ret < 0) | ||
854 | { | ||
855 | gnutls_assert (); | ||
856 | goto error; | ||
857 | } | ||
858 | |||
859 | ret = _gnutls_x509_read_der_int (tmp.data, tmp.size, &pkey->params[4]); | ||
860 | _gnutls_free_datum (&tmp); | ||
861 | |||
862 | if (ret < 0) | ||
863 | { | ||
864 | gnutls_assert (); | ||
865 | goto error; | ||
866 | } | ||
867 | |||
868 | ret = | ||
869 | _gnutls_x509_read_value (pkcs8_asn, "privateKeyAlgorithm.parameters", | ||
870 | &tmp, 0); | ||
871 | if (ret < 0) | ||
872 | { | ||
873 | gnutls_assert (); | ||
874 | goto error; | ||
875 | } | ||
876 | |||
877 | ret = _gnutls_x509_read_dsa_params (tmp.data, tmp.size, pkey->params); | ||
878 | _gnutls_free_datum (&tmp); | ||
879 | if (ret < 0) | ||
880 | { | ||
881 | gnutls_assert (); | ||
882 | goto error; | ||
883 | } | ||
884 | |||
885 | /* the public key can be generated as g^x mod p */ | ||
886 | pkey->params[3] = _gnutls_mpi_alloc_like (pkey->params[0]); | ||
887 | if (pkey->params[3] == NULL) | ||
888 | { | ||
889 | gnutls_assert (); | ||
890 | goto error; | ||
891 | } | ||
892 | |||
893 | _gnutls_mpi_powm (pkey->params[3], pkey->params[2], pkey->params[4], | ||
894 | pkey->params[0]); | ||
895 | |||
896 | if (!pkey->crippled) | ||
897 | { | ||
898 | ret = _gnutls_asn1_encode_dsa (&pkey->key, pkey->params); | ||
899 | if (ret < 0) | ||
900 | { | ||
901 | gnutls_assert (); | ||
902 | goto error; | ||
903 | } | ||
904 | } | ||
905 | |||
906 | pkey->params_size = DSA_PRIVATE_PARAMS; | ||
907 | |||
908 | return 0; | ||
909 | |||
910 | error: | ||
911 | gnutls_x509_privkey_deinit (pkey); | ||
912 | return ret; | ||
913 | } | ||
914 | |||
915 | static int | ||
916 | decode_private_key_info (const gnutls_datum_t * der, | ||
917 | gnutls_x509_privkey_t pkey) | ||
918 | { | ||
919 | int result, len; | ||
920 | opaque oid[64]; | ||
921 | ASN1_TYPE pkcs8_asn = ASN1_TYPE_EMPTY; | ||
922 | |||
923 | if ((result = | ||
924 | asn1_create_element (_gnutls_get_pkix (), | ||
925 | "PKIX1.pkcs-8-PrivateKeyInfo", | ||
926 | &pkcs8_asn)) != ASN1_SUCCESS) | ||
927 | { | ||
928 | gnutls_assert (); | ||
929 | result = _gnutls_asn2err (result); | ||
930 | goto error; | ||
931 | } | ||
932 | |||
933 | result = asn1_der_decoding (&pkcs8_asn, der->data, der->size, NULL); | ||
934 | if (result != ASN1_SUCCESS) | ||
935 | { | ||
936 | gnutls_assert (); | ||
937 | result = _gnutls_asn2err (result); | ||
938 | goto error; | ||
939 | } | ||
940 | |||
941 | /* Check the private key algorithm OID | ||
942 | */ | ||
943 | len = sizeof (oid); | ||
944 | result = | ||
945 | asn1_read_value (pkcs8_asn, "privateKeyAlgorithm.algorithm", oid, &len); | ||
946 | if (result != ASN1_SUCCESS) | ||
947 | { | ||
948 | gnutls_assert (); | ||
949 | result = _gnutls_asn2err (result); | ||
950 | goto error; | ||
951 | } | ||
952 | |||
953 | /* we only support RSA and DSA private keys. | ||
954 | */ | ||
955 | if (strcmp (oid, PK_PKIX1_RSA_OID) == 0) | ||
956 | pkey->pk_algorithm = GNUTLS_PK_RSA; | ||
957 | else | ||
958 | { | ||
959 | gnutls_assert (); | ||
960 | _gnutls_x509_log | ||
961 | ("PKCS #8 private key OID '%s' is unsupported.\n", oid); | ||
962 | result = GNUTLS_E_UNKNOWN_PK_ALGORITHM; | ||
963 | goto error; | ||
964 | } | ||
965 | |||
966 | /* Get the DER encoding of the actual private key. | ||
967 | */ | ||
968 | |||
969 | if (pkey->pk_algorithm == GNUTLS_PK_RSA) | ||
970 | result = _decode_pkcs8_rsa_key (pkcs8_asn, pkey); | ||
971 | if (result < 0) | ||
972 | { | ||
973 | gnutls_assert (); | ||
974 | return result; | ||
975 | } | ||
976 | |||
977 | result = 0; | ||
978 | |||
979 | error: | ||
980 | asn1_delete_structure (&pkcs8_asn); | ||
981 | |||
982 | return result; | ||
983 | |||
984 | } | ||
985 | |||
986 | /** | ||
987 | * gnutls_x509_privkey_import_pkcs8 - This function will import a DER or PEM PKCS8 encoded key | ||
988 | * @key: The structure to store the parsed key | ||
989 | * @data: The DER or PEM encoded key. | ||
990 | * @format: One of DER or PEM | ||
991 | * @password: the password to decrypt the key (if it is encrypted). | ||
992 | * @flags: 0 if encrypted or GNUTLS_PKCS_PLAIN if not encrypted. | ||
993 | * | ||
994 | * This function will convert the given DER or PEM encoded PKCS8 2.0 encrypted key | ||
995 | * to the native gnutls_x509_privkey_t format. The output will be stored in @key. | ||
996 | * Both RSA and DSA keys can be imported, and flags can only be used to indicate | ||
997 | * an unencrypted key. | ||
998 | * | ||
999 | * The @password can be either ASCII or UTF-8 in the default PBES2 | ||
1000 | * encryption schemas, or ASCII for the PKCS12 schemas. | ||
1001 | * | ||
1002 | * If the Certificate is PEM encoded it should have a header of "ENCRYPTED PRIVATE KEY", | ||
1003 | * or "PRIVATE KEY". You only need to specify the flags if the key is DER encoded, since | ||
1004 | * in that case the encryption status cannot be auto-detected. | ||
1005 | * | ||
1006 | * Returns 0 on success. | ||
1007 | * | ||
1008 | **/ | ||
1009 | int | ||
1010 | gnutls_x509_privkey_import_pkcs8 (gnutls_x509_privkey_t key, | ||
1011 | const gnutls_datum_t * data, | ||
1012 | gnutls_x509_crt_fmt_t format, | ||
1013 | const char *password, unsigned int flags) | ||
1014 | { | ||
1015 | int result = 0, need_free = 0; | ||
1016 | gnutls_datum_t _data; | ||
1017 | |||
1018 | if (key == NULL) | ||
1019 | { | ||
1020 | gnutls_assert (); | ||
1021 | return GNUTLS_E_INVALID_REQUEST; | ||
1022 | } | ||
1023 | |||
1024 | _data.data = data->data; | ||
1025 | _data.size = data->size; | ||
1026 | |||
1027 | key->pk_algorithm = GNUTLS_PK_UNKNOWN; | ||
1028 | |||
1029 | /* If the Certificate is in PEM format then decode it | ||
1030 | */ | ||
1031 | if (format == GNUTLS_X509_FMT_PEM) | ||
1032 | { | ||
1033 | opaque *out; | ||
1034 | |||
1035 | /* Try the first header | ||
1036 | */ | ||
1037 | result = | ||
1038 | _gnutls_fbase64_decode (PEM_UNENCRYPTED_PKCS8, | ||
1039 | data->data, data->size, &out); | ||
1040 | |||
1041 | if (result < 0) | ||
1042 | { /* Try the encrypted header | ||
1043 | */ | ||
1044 | result = | ||
1045 | _gnutls_fbase64_decode (PEM_PKCS8, data->data, data->size, &out); | ||
1046 | |||
1047 | if (result <= 0) | ||
1048 | { | ||
1049 | if (result == 0) | ||
1050 | result = GNUTLS_E_INTERNAL_ERROR; | ||
1051 | gnutls_assert (); | ||
1052 | return result; | ||
1053 | } | ||
1054 | } | ||
1055 | else if (flags == 0) | ||
1056 | flags |= GNUTLS_PKCS_PLAIN; | ||
1057 | |||
1058 | _data.data = out; | ||
1059 | _data.size = result; | ||
1060 | |||
1061 | need_free = 1; | ||
1062 | } | ||
1063 | |||
1064 | if (flags & GNUTLS_PKCS_PLAIN) | ||
1065 | { | ||
1066 | result = decode_private_key_info (&_data, key); | ||
1067 | } | ||
1068 | else | ||
1069 | { /* encrypted. */ | ||
1070 | result = decode_pkcs8_key (&_data, password, key); | ||
1071 | } | ||
1072 | |||
1073 | if (result < 0) | ||
1074 | { | ||
1075 | gnutls_assert (); | ||
1076 | goto cleanup; | ||
1077 | } | ||
1078 | |||
1079 | if (need_free) | ||
1080 | _gnutls_free_datum (&_data); | ||
1081 | |||
1082 | /* The key has now been decoded. | ||
1083 | */ | ||
1084 | |||
1085 | return 0; | ||
1086 | |||
1087 | cleanup: | ||
1088 | key->pk_algorithm = GNUTLS_PK_UNKNOWN; | ||
1089 | if (need_free) | ||
1090 | _gnutls_free_datum (&_data); | ||
1091 | return result; | ||
1092 | } | ||
1093 | |||
1094 | /* Reads the PBKDF2 parameters. | ||
1095 | */ | ||
1096 | static int | ||
1097 | read_pbkdf2_params (ASN1_TYPE pbes2_asn, | ||
1098 | const gnutls_datum_t * der, struct pbkdf2_params *params) | ||
1099 | { | ||
1100 | int params_start, params_end; | ||
1101 | int params_len, len, result; | ||
1102 | ASN1_TYPE pbkdf2_asn = ASN1_TYPE_EMPTY; | ||
1103 | char oid[64]; | ||
1104 | |||
1105 | memset (params, 0, sizeof (params)); | ||
1106 | |||
1107 | /* Check the key derivation algorithm | ||
1108 | */ | ||
1109 | len = sizeof (oid); | ||
1110 | result = | ||
1111 | asn1_read_value (pbes2_asn, "keyDerivationFunc.algorithm", oid, &len); | ||
1112 | if (result != ASN1_SUCCESS) | ||
1113 | { | ||
1114 | gnutls_assert (); | ||
1115 | return _gnutls_asn2err (result); | ||
1116 | } | ||
1117 | _gnutls_hard_log ("keyDerivationFunc.algorithm: %s\n", oid); | ||
1118 | |||
1119 | if (strcmp (oid, PBKDF2_OID) != 0) | ||
1120 | { | ||
1121 | gnutls_assert (); | ||
1122 | _gnutls_x509_log | ||
1123 | ("PKCS #8 key derivation OID '%s' is unsupported.\n", oid); | ||
1124 | return _gnutls_asn2err (result); | ||
1125 | } | ||
1126 | |||
1127 | result = | ||
1128 | asn1_der_decoding_startEnd (pbes2_asn, der->data, der->size, | ||
1129 | "keyDerivationFunc.parameters", | ||
1130 | ¶ms_start, ¶ms_end); | ||
1131 | if (result != ASN1_SUCCESS) | ||
1132 | { | ||
1133 | gnutls_assert (); | ||
1134 | return _gnutls_asn2err (result); | ||
1135 | } | ||
1136 | params_len = params_end - params_start + 1; | ||
1137 | |||
1138 | /* Now check the key derivation and the encryption | ||
1139 | * functions. | ||
1140 | */ | ||
1141 | if ((result = | ||
1142 | asn1_create_element (_gnutls_get_pkix (), | ||
1143 | "PKIX1.pkcs-5-PBKDF2-params", | ||
1144 | &pbkdf2_asn)) != ASN1_SUCCESS) | ||
1145 | { | ||
1146 | gnutls_assert (); | ||
1147 | return _gnutls_asn2err (result); | ||
1148 | } | ||
1149 | |||
1150 | result = | ||
1151 | asn1_der_decoding (&pbkdf2_asn, &der->data[params_start], | ||
1152 | params_len, NULL); | ||
1153 | if (result != ASN1_SUCCESS) | ||
1154 | { | ||
1155 | gnutls_assert (); | ||
1156 | result = _gnutls_asn2err (result); | ||
1157 | goto error; | ||
1158 | } | ||
1159 | |||
1160 | /* read the salt */ | ||
1161 | params->salt_size = sizeof (params->salt); | ||
1162 | result = | ||
1163 | asn1_read_value (pbkdf2_asn, "salt.specified", params->salt, | ||
1164 | ¶ms->salt_size); | ||
1165 | if (result != ASN1_SUCCESS) | ||
1166 | { | ||
1167 | gnutls_assert (); | ||
1168 | result = _gnutls_asn2err (result); | ||
1169 | goto error; | ||
1170 | } | ||
1171 | _gnutls_hard_log ("salt.specified.size: %d\n", params->salt_size); | ||
1172 | |||
1173 | /* read the iteration count | ||
1174 | */ | ||
1175 | result = | ||
1176 | _gnutls_x509_read_uint (pbkdf2_asn, "iterationCount", | ||
1177 | ¶ms->iter_count); | ||
1178 | if (result != ASN1_SUCCESS) | ||
1179 | { | ||
1180 | gnutls_assert (); | ||
1181 | goto error; | ||
1182 | } | ||
1183 | _gnutls_hard_log ("iterationCount: %d\n", params->iter_count); | ||
1184 | |||
1185 | /* read the keylength, if it is set. | ||
1186 | */ | ||
1187 | result = | ||
1188 | _gnutls_x509_read_uint (pbkdf2_asn, "keyLength", ¶ms->key_size); | ||
1189 | if (result < 0) | ||
1190 | { | ||
1191 | params->key_size = 0; | ||
1192 | } | ||
1193 | _gnutls_hard_log ("keyLength: %d\n", params->key_size); | ||
1194 | |||
1195 | /* We don't read the PRF. We only use the default. | ||
1196 | */ | ||
1197 | |||
1198 | return 0; | ||
1199 | |||
1200 | error: | ||
1201 | asn1_delete_structure (&pbkdf2_asn); | ||
1202 | return result; | ||
1203 | |||
1204 | } | ||
1205 | |||
1206 | /* Reads the PBE parameters from PKCS-12 schemas (*&#%*&#% RSA). | ||
1207 | */ | ||
1208 | static int | ||
1209 | read_pkcs12_kdf_params (ASN1_TYPE pbes2_asn, struct pbkdf2_params *params) | ||
1210 | { | ||
1211 | int result; | ||
1212 | |||
1213 | memset (params, 0, sizeof (params)); | ||
1214 | |||
1215 | /* read the salt */ | ||
1216 | params->salt_size = sizeof (params->salt); | ||
1217 | result = | ||
1218 | asn1_read_value (pbes2_asn, "salt", params->salt, ¶ms->salt_size); | ||
1219 | if (result != ASN1_SUCCESS) | ||
1220 | { | ||
1221 | gnutls_assert (); | ||
1222 | result = _gnutls_asn2err (result); | ||
1223 | goto error; | ||
1224 | } | ||
1225 | _gnutls_hard_log ("salt.size: %d\n", params->salt_size); | ||
1226 | |||
1227 | /* read the iteration count | ||
1228 | */ | ||
1229 | result = | ||
1230 | _gnutls_x509_read_uint (pbes2_asn, "iterations", ¶ms->iter_count); | ||
1231 | if (result != ASN1_SUCCESS) | ||
1232 | { | ||
1233 | gnutls_assert (); | ||
1234 | goto error; | ||
1235 | } | ||
1236 | _gnutls_hard_log ("iterationCount: %d\n", params->iter_count); | ||
1237 | |||
1238 | params->key_size = 0; | ||
1239 | |||
1240 | return 0; | ||
1241 | |||
1242 | error: | ||
1243 | return result; | ||
1244 | |||
1245 | } | ||
1246 | |||
1247 | /* Writes the PBE parameters for PKCS-12 schemas. | ||
1248 | */ | ||
1249 | static int | ||
1250 | write_pkcs12_kdf_params (ASN1_TYPE pbes2_asn, | ||
1251 | const struct pbkdf2_params *kdf_params) | ||
1252 | { | ||
1253 | int result; | ||
1254 | |||
1255 | /* write the salt | ||
1256 | */ | ||
1257 | result = | ||
1258 | asn1_write_value (pbes2_asn, "salt", | ||
1259 | kdf_params->salt, kdf_params->salt_size); | ||
1260 | if (result != ASN1_SUCCESS) | ||
1261 | { | ||
1262 | gnutls_assert (); | ||
1263 | result = _gnutls_asn2err (result); | ||
1264 | goto error; | ||
1265 | } | ||
1266 | _gnutls_hard_log ("salt.size: %d\n", kdf_params->salt_size); | ||
1267 | |||
1268 | /* write the iteration count | ||
1269 | */ | ||
1270 | result = | ||
1271 | _gnutls_x509_write_uint32 (pbes2_asn, "iterations", | ||
1272 | kdf_params->iter_count); | ||
1273 | if (result < 0) | ||
1274 | { | ||
1275 | gnutls_assert (); | ||
1276 | goto error; | ||
1277 | } | ||
1278 | _gnutls_hard_log ("iterationCount: %d\n", kdf_params->iter_count); | ||
1279 | |||
1280 | return 0; | ||
1281 | |||
1282 | error: | ||
1283 | return result; | ||
1284 | |||
1285 | } | ||
1286 | |||
1287 | /* Converts an OID to a gnutls cipher type. | ||
1288 | */ | ||
1289 | inline static int | ||
1290 | oid2cipher (const char *oid, gnutls_cipher_algorithm_t * algo) | ||
1291 | { | ||
1292 | |||
1293 | *algo = 0; | ||
1294 | |||
1295 | if (strcmp (oid, DES_EDE3_CBC_OID) == 0) | ||
1296 | { | ||
1297 | *algo = GNUTLS_CIPHER_3DES_CBC; | ||
1298 | return 0; | ||
1299 | } | ||
1300 | |||
1301 | if (strcmp (oid, DES_CBC_OID) == 0) | ||
1302 | { | ||
1303 | *algo = GNUTLS_CIPHER_DES_CBC; | ||
1304 | return 0; | ||
1305 | } | ||
1306 | |||
1307 | _gnutls_x509_log ("PKCS #8 encryption OID '%s' is unsupported.\n", oid); | ||
1308 | return GNUTLS_E_UNKNOWN_CIPHER_TYPE; | ||
1309 | } | ||
1310 | |||
1311 | static int | ||
1312 | read_pbe_enc_params (ASN1_TYPE pbes2_asn, | ||
1313 | const gnutls_datum_t * der, | ||
1314 | struct pbe_enc_params *params) | ||
1315 | { | ||
1316 | int params_start, params_end; | ||
1317 | int params_len, len, result; | ||
1318 | ASN1_TYPE pbe_asn = ASN1_TYPE_EMPTY; | ||
1319 | char oid[64]; | ||
1320 | |||
1321 | memset (params, 0, sizeof (params)); | ||
1322 | |||
1323 | /* Check the encryption algorithm | ||
1324 | */ | ||
1325 | len = sizeof (oid); | ||
1326 | result = | ||
1327 | asn1_read_value (pbes2_asn, "encryptionScheme.algorithm", oid, &len); | ||
1328 | if (result != ASN1_SUCCESS) | ||
1329 | { | ||
1330 | gnutls_assert (); | ||
1331 | goto error; | ||
1332 | } | ||
1333 | _gnutls_hard_log ("encryptionScheme.algorithm: %s\n", oid); | ||
1334 | |||
1335 | if ((result = oid2cipher (oid, ¶ms->cipher)) < 0) | ||
1336 | { | ||
1337 | gnutls_assert (); | ||
1338 | goto error; | ||
1339 | } | ||
1340 | |||
1341 | result = | ||
1342 | asn1_der_decoding_startEnd (pbes2_asn, der->data, der->size, | ||
1343 | "encryptionScheme.parameters", | ||
1344 | ¶ms_start, ¶ms_end); | ||
1345 | if (result != ASN1_SUCCESS) | ||
1346 | { | ||
1347 | gnutls_assert (); | ||
1348 | return _gnutls_asn2err (result); | ||
1349 | } | ||
1350 | params_len = params_end - params_start + 1; | ||
1351 | |||
1352 | /* Now check the encryption parameters. | ||
1353 | */ | ||
1354 | if ((result = | ||
1355 | asn1_create_element (_gnutls_get_pkix (), | ||
1356 | "PKIX1.pkcs-5-des-EDE3-CBC-params", | ||
1357 | &pbe_asn)) != ASN1_SUCCESS) | ||
1358 | { | ||
1359 | gnutls_assert (); | ||
1360 | return _gnutls_asn2err (result); | ||
1361 | } | ||
1362 | |||
1363 | result = | ||
1364 | asn1_der_decoding (&pbe_asn, &der->data[params_start], params_len, NULL); | ||
1365 | if (result != ASN1_SUCCESS) | ||
1366 | { | ||
1367 | gnutls_assert (); | ||
1368 | result = _gnutls_asn2err (result); | ||
1369 | goto error; | ||
1370 | } | ||
1371 | |||
1372 | /* read the IV */ | ||
1373 | params->iv_size = sizeof (params->iv); | ||
1374 | result = asn1_read_value (pbe_asn, "", params->iv, ¶ms->iv_size); | ||
1375 | if (result != ASN1_SUCCESS) | ||
1376 | { | ||
1377 | gnutls_assert (); | ||
1378 | result = _gnutls_asn2err (result); | ||
1379 | goto error; | ||
1380 | } | ||
1381 | _gnutls_hard_log ("IV.size: %d\n", params->iv_size); | ||
1382 | |||
1383 | return 0; | ||
1384 | |||
1385 | error: | ||
1386 | asn1_delete_structure (&pbe_asn); | ||
1387 | return result; | ||
1388 | |||
1389 | } | ||
1390 | |||
1391 | static int | ||
1392 | decrypt_data (schema_id schema, ASN1_TYPE pkcs8_asn, | ||
1393 | const char *root, const char *password, | ||
1394 | const struct pbkdf2_params *kdf_params, | ||
1395 | const struct pbe_enc_params *enc_params, | ||
1396 | gnutls_datum_t * decrypted_data) | ||
1397 | { | ||
1398 | int result; | ||
1399 | int data_size; | ||
1400 | opaque *data = NULL, *key = NULL; | ||
1401 | gnutls_datum_t dkey, d_iv; | ||
1402 | cipher_hd_t ch = NULL; | ||
1403 | int key_size; | ||
1404 | |||
1405 | data_size = 0; | ||
1406 | result = asn1_read_value (pkcs8_asn, root, NULL, &data_size); | ||
1407 | if (result != ASN1_MEM_ERROR) | ||
1408 | { | ||
1409 | gnutls_assert (); | ||
1410 | return _gnutls_asn2err (result); | ||
1411 | } | ||
1412 | |||
1413 | data = gnutls_malloc (data_size); | ||
1414 | if (data == NULL) | ||
1415 | { | ||
1416 | gnutls_assert (); | ||
1417 | return GNUTLS_E_MEMORY_ERROR; | ||
1418 | } | ||
1419 | |||
1420 | result = asn1_read_value (pkcs8_asn, root, data, &data_size); | ||
1421 | if (result != ASN1_SUCCESS) | ||
1422 | { | ||
1423 | gnutls_assert (); | ||
1424 | result = _gnutls_asn2err (result); | ||
1425 | goto error; | ||
1426 | } | ||
1427 | |||
1428 | if (kdf_params->key_size == 0) | ||
1429 | { | ||
1430 | key_size = gnutls_cipher_get_key_size (enc_params->cipher); | ||
1431 | } | ||
1432 | else | ||
1433 | key_size = kdf_params->key_size; | ||
1434 | |||
1435 | key = gnutls_alloca (key_size); | ||
1436 | if (key == NULL) | ||
1437 | { | ||
1438 | gnutls_assert (); | ||
1439 | result = GNUTLS_E_MEMORY_ERROR; | ||
1440 | goto error; | ||
1441 | } | ||
1442 | |||
1443 | /* generate the key | ||
1444 | */ | ||
1445 | if (schema == PBES2) | ||
1446 | { | ||
1447 | result = gc_pbkdf2_sha1 (password, strlen (password), | ||
1448 | kdf_params->salt, kdf_params->salt_size, | ||
1449 | kdf_params->iter_count, key, key_size); | ||
1450 | |||
1451 | if (result != GC_OK) | ||
1452 | { | ||
1453 | gnutls_assert (); | ||
1454 | result = GNUTLS_E_DECRYPTION_FAILED; | ||
1455 | goto error; | ||
1456 | } | ||
1457 | } | ||
1458 | else | ||
1459 | { | ||
1460 | result = | ||
1461 | _pkcs12_string_to_key (1 /*KEY*/, kdf_params->salt, | ||
1462 | kdf_params->salt_size, | ||
1463 | kdf_params->iter_count, password, | ||
1464 | key_size, key); | ||
1465 | |||
1466 | if (result < 0) | ||
1467 | { | ||
1468 | gnutls_assert (); | ||
1469 | goto error; | ||
1470 | } | ||
1471 | } | ||
1472 | |||
1473 | /* do the decryption. | ||
1474 | */ | ||
1475 | dkey.data = key; | ||
1476 | dkey.size = key_size; | ||
1477 | |||
1478 | d_iv.data = (opaque *) enc_params->iv; | ||
1479 | d_iv.size = enc_params->iv_size; | ||
1480 | ch = _gnutls_cipher_init (enc_params->cipher, &dkey, &d_iv); | ||
1481 | |||
1482 | gnutls_afree (key); | ||
1483 | key = NULL; | ||
1484 | |||
1485 | if (ch == NULL) | ||
1486 | { | ||
1487 | gnutls_assert (); | ||
1488 | result = GNUTLS_E_DECRYPTION_FAILED; | ||
1489 | goto error; | ||
1490 | } | ||
1491 | |||
1492 | result = _gnutls_cipher_decrypt (ch, data, data_size); | ||
1493 | if (result < 0) | ||
1494 | { | ||
1495 | gnutls_assert (); | ||
1496 | goto error; | ||
1497 | } | ||
1498 | |||
1499 | decrypted_data->data = data; | ||
1500 | |||
1501 | if (_gnutls_cipher_get_block_size (enc_params->cipher) != 1) | ||
1502 | decrypted_data->size = data_size - data[data_size - 1]; | ||
1503 | else | ||
1504 | decrypted_data->size = data_size; | ||
1505 | |||
1506 | _gnutls_cipher_deinit (ch); | ||
1507 | |||
1508 | return 0; | ||
1509 | |||
1510 | error: | ||
1511 | gnutls_free (data); | ||
1512 | gnutls_afree (key); | ||
1513 | if (ch != NULL) | ||
1514 | _gnutls_cipher_deinit (ch); | ||
1515 | return result; | ||
1516 | } | ||
1517 | |||
1518 | /* Writes the PBKDF2 parameters. | ||
1519 | */ | ||
1520 | static int | ||
1521 | write_pbkdf2_params (ASN1_TYPE pbes2_asn, | ||
1522 | const struct pbkdf2_params *kdf_params) | ||
1523 | { | ||
1524 | int result; | ||
1525 | ASN1_TYPE pbkdf2_asn = ASN1_TYPE_EMPTY; | ||
1526 | opaque tmp[64]; | ||
1527 | |||
1528 | /* Write the key derivation algorithm | ||
1529 | */ | ||
1530 | result = | ||
1531 | asn1_write_value (pbes2_asn, "keyDerivationFunc.algorithm", | ||
1532 | PBKDF2_OID, 1); | ||
1533 | if (result != ASN1_SUCCESS) | ||
1534 | { | ||
1535 | gnutls_assert (); | ||
1536 | return _gnutls_asn2err (result); | ||
1537 | } | ||
1538 | |||
1539 | /* Now write the key derivation and the encryption | ||
1540 | * functions. | ||
1541 | */ | ||
1542 | if ((result = | ||
1543 | asn1_create_element (_gnutls_get_pkix (), | ||
1544 | "PKIX1.pkcs-5-PBKDF2-params", | ||
1545 | &pbkdf2_asn)) != ASN1_SUCCESS) | ||
1546 | { | ||
1547 | gnutls_assert (); | ||
1548 | return _gnutls_asn2err (result); | ||
1549 | } | ||
1550 | |||
1551 | result = asn1_write_value (pbkdf2_asn, "salt", "specified", 1); | ||
1552 | if (result != ASN1_SUCCESS) | ||
1553 | { | ||
1554 | gnutls_assert (); | ||
1555 | result = _gnutls_asn2err (result); | ||
1556 | goto error; | ||
1557 | } | ||
1558 | |||
1559 | /* write the salt | ||
1560 | */ | ||
1561 | result = | ||
1562 | asn1_write_value (pbkdf2_asn, "salt.specified", | ||
1563 | kdf_params->salt, kdf_params->salt_size); | ||
1564 | if (result != ASN1_SUCCESS) | ||
1565 | { | ||
1566 | gnutls_assert (); | ||
1567 | result = _gnutls_asn2err (result); | ||
1568 | goto error; | ||
1569 | } | ||
1570 | _gnutls_hard_log ("salt.specified.size: %d\n", kdf_params->salt_size); | ||
1571 | |||
1572 | /* write the iteration count | ||
1573 | */ | ||
1574 | _gnutls_write_uint32 (kdf_params->iter_count, tmp); | ||
1575 | |||
1576 | result = asn1_write_value (pbkdf2_asn, "iterationCount", tmp, 4); | ||
1577 | if (result != ASN1_SUCCESS) | ||
1578 | { | ||
1579 | gnutls_assert (); | ||
1580 | result = _gnutls_asn2err (result); | ||
1581 | goto error; | ||
1582 | } | ||
1583 | _gnutls_hard_log ("iterationCount: %d\n", kdf_params->iter_count); | ||
1584 | |||
1585 | /* write the keylength, if it is set. | ||
1586 | */ | ||
1587 | result = asn1_write_value (pbkdf2_asn, "keyLength", NULL, 0); | ||
1588 | if (result != ASN1_SUCCESS) | ||
1589 | { | ||
1590 | gnutls_assert (); | ||
1591 | result = _gnutls_asn2err (result); | ||
1592 | goto error; | ||
1593 | } | ||
1594 | |||
1595 | /* We write an emptry prf. | ||
1596 | */ | ||
1597 | result = asn1_write_value (pbkdf2_asn, "prf", NULL, 0); | ||
1598 | if (result != ASN1_SUCCESS) | ||
1599 | { | ||
1600 | gnutls_assert (); | ||
1601 | result = _gnutls_asn2err (result); | ||
1602 | goto error; | ||
1603 | } | ||
1604 | |||
1605 | /* now encode them an put the DER output | ||
1606 | * in the keyDerivationFunc.parameters | ||
1607 | */ | ||
1608 | result = _gnutls_x509_der_encode_and_copy (pbkdf2_asn, "", | ||
1609 | pbes2_asn, | ||
1610 | "keyDerivationFunc.parameters", | ||
1611 | 0); | ||
1612 | if (result < 0) | ||
1613 | { | ||
1614 | gnutls_assert (); | ||
1615 | goto error; | ||
1616 | } | ||
1617 | |||
1618 | return 0; | ||
1619 | |||
1620 | error: | ||
1621 | asn1_delete_structure (&pbkdf2_asn); | ||
1622 | return result; | ||
1623 | |||
1624 | } | ||
1625 | |||
1626 | static int | ||
1627 | write_pbe_enc_params (ASN1_TYPE pbes2_asn, | ||
1628 | const struct pbe_enc_params *params) | ||
1629 | { | ||
1630 | int result; | ||
1631 | ASN1_TYPE pbe_asn = ASN1_TYPE_EMPTY; | ||
1632 | |||
1633 | /* Write the encryption algorithm | ||
1634 | */ | ||
1635 | result = | ||
1636 | asn1_write_value (pbes2_asn, "encryptionScheme.algorithm", | ||
1637 | DES_EDE3_CBC_OID, 1); | ||
1638 | if (result != ASN1_SUCCESS) | ||
1639 | { | ||
1640 | gnutls_assert (); | ||
1641 | goto error; | ||
1642 | } | ||
1643 | _gnutls_hard_log ("encryptionScheme.algorithm: %s\n", DES_EDE3_CBC_OID); | ||
1644 | |||
1645 | /* Now check the encryption parameters. | ||
1646 | */ | ||
1647 | if ((result = | ||
1648 | asn1_create_element (_gnutls_get_pkix (), | ||
1649 | "PKIX1.pkcs-5-des-EDE3-CBC-params", | ||
1650 | &pbe_asn)) != ASN1_SUCCESS) | ||
1651 | { | ||
1652 | gnutls_assert (); | ||
1653 | return _gnutls_asn2err (result); | ||
1654 | } | ||
1655 | |||
1656 | /* read the salt */ | ||
1657 | result = asn1_write_value (pbe_asn, "", params->iv, params->iv_size); | ||
1658 | if (result != ASN1_SUCCESS) | ||
1659 | { | ||
1660 | gnutls_assert (); | ||
1661 | result = _gnutls_asn2err (result); | ||
1662 | goto error; | ||
1663 | } | ||
1664 | _gnutls_hard_log ("IV.size: %d\n", params->iv_size); | ||
1665 | |||
1666 | /* now encode them an put the DER output | ||
1667 | * in the encryptionScheme.parameters | ||
1668 | */ | ||
1669 | result = _gnutls_x509_der_encode_and_copy (pbe_asn, "", | ||
1670 | pbes2_asn, | ||
1671 | "encryptionScheme.parameters", | ||
1672 | 0); | ||
1673 | if (result < 0) | ||
1674 | { | ||
1675 | gnutls_assert (); | ||
1676 | goto error; | ||
1677 | } | ||
1678 | |||
1679 | return 0; | ||
1680 | |||
1681 | error: | ||
1682 | asn1_delete_structure (&pbe_asn); | ||
1683 | return result; | ||
1684 | |||
1685 | } | ||
1686 | |||
1687 | /* Generates a key and also stores the key parameters. | ||
1688 | */ | ||
1689 | static int | ||
1690 | generate_key (schema_id schema, | ||
1691 | const char *password, | ||
1692 | struct pbkdf2_params *kdf_params, | ||
1693 | struct pbe_enc_params *enc_params, gnutls_datum_t * key) | ||
1694 | { | ||
1695 | opaque rnd[2]; | ||
1696 | int ret; | ||
1697 | |||
1698 | /* We should use the flags here to use different | ||
1699 | * encryption algorithms etc. | ||
1700 | */ | ||
1701 | |||
1702 | if (schema == PKCS12_ARCFOUR_SHA1) | ||
1703 | enc_params->cipher = GNUTLS_CIPHER_ARCFOUR_128; | ||
1704 | else if (schema == PKCS12_3DES_SHA1) | ||
1705 | enc_params->cipher = GNUTLS_CIPHER_3DES_CBC; | ||
1706 | else if (schema == PKCS12_RC2_40_SHA1) | ||
1707 | enc_params->cipher = GNUTLS_CIPHER_RC2_40_CBC; | ||
1708 | |||
1709 | if (gc_pseudo_random (rnd, 2) != GC_OK) | ||
1710 | { | ||
1711 | gnutls_assert (); | ||
1712 | return GNUTLS_E_RANDOM_FAILED; | ||
1713 | } | ||
1714 | |||
1715 | /* generate salt */ | ||
1716 | |||
1717 | if (schema == PBES2) | ||
1718 | { | ||
1719 | kdf_params->salt_size = MIN (sizeof (kdf_params->salt), (unsigned) (10 + (rnd[1] % 10))); | ||
1720 | } | ||
1721 | else | ||
1722 | kdf_params->salt_size = 8; | ||
1723 | |||
1724 | if (gc_pseudo_random (kdf_params->salt, kdf_params->salt_size) != GC_OK) | ||
1725 | { | ||
1726 | gnutls_assert (); | ||
1727 | return GNUTLS_E_RANDOM_FAILED; | ||
1728 | } | ||
1729 | |||
1730 | kdf_params->iter_count = 256 + rnd[0]; | ||
1731 | key->size = kdf_params->key_size = | ||
1732 | gnutls_cipher_get_key_size (enc_params->cipher); | ||
1733 | |||
1734 | enc_params->iv_size = _gnutls_cipher_get_iv_size (enc_params->cipher); | ||
1735 | |||
1736 | key->data = gnutls_secure_malloc (key->size); | ||
1737 | if (key->data == NULL) | ||
1738 | { | ||
1739 | gnutls_assert (); | ||
1740 | return GNUTLS_E_MEMORY_ERROR; | ||
1741 | } | ||
1742 | |||
1743 | /* now generate the key. | ||
1744 | */ | ||
1745 | |||
1746 | if (schema == PBES2) | ||
1747 | { | ||
1748 | |||
1749 | ret = gc_pbkdf2_sha1 (password, strlen (password), | ||
1750 | kdf_params->salt, kdf_params->salt_size, | ||
1751 | kdf_params->iter_count, | ||
1752 | key->data, kdf_params->key_size); | ||
1753 | if (ret != GC_OK) | ||
1754 | { | ||
1755 | gnutls_assert (); | ||
1756 | return GNUTLS_E_ENCRYPTION_FAILED; | ||
1757 | } | ||
1758 | |||
1759 | if (enc_params->iv_size && | ||
1760 | gc_nonce (enc_params->iv, enc_params->iv_size) != GC_OK) | ||
1761 | { | ||
1762 | gnutls_assert (); | ||
1763 | return GNUTLS_E_RANDOM_FAILED; | ||
1764 | } | ||
1765 | } | ||
1766 | else | ||
1767 | { /* PKCS12 schemas */ | ||
1768 | ret = | ||
1769 | _pkcs12_string_to_key (1 /*KEY*/, kdf_params->salt, | ||
1770 | kdf_params->salt_size, | ||
1771 | kdf_params->iter_count, password, | ||
1772 | kdf_params->key_size, key->data); | ||
1773 | if (ret < 0) | ||
1774 | { | ||
1775 | gnutls_assert (); | ||
1776 | return ret; | ||
1777 | } | ||
1778 | |||
1779 | /* Now generate the IV | ||
1780 | */ | ||
1781 | if (enc_params->iv_size) | ||
1782 | { | ||
1783 | ret = | ||
1784 | _pkcs12_string_to_key (2 /*IV*/, kdf_params->salt, | ||
1785 | kdf_params->salt_size, | ||
1786 | kdf_params->iter_count, password, | ||
1787 | enc_params->iv_size, enc_params->iv); | ||
1788 | if (ret < 0) | ||
1789 | { | ||
1790 | gnutls_assert (); | ||
1791 | return ret; | ||
1792 | } | ||
1793 | } | ||
1794 | } | ||
1795 | |||
1796 | return 0; | ||
1797 | } | ||
1798 | |||
1799 | /* Encodes the parameters to be written in the encryptionAlgorithm.parameters | ||
1800 | * part. | ||
1801 | */ | ||
1802 | static int | ||
1803 | write_schema_params (schema_id schema, ASN1_TYPE pkcs8_asn, | ||
1804 | const char *where, | ||
1805 | const struct pbkdf2_params *kdf_params, | ||
1806 | const struct pbe_enc_params *enc_params) | ||
1807 | { | ||
1808 | int result; | ||
1809 | ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY; | ||
1810 | |||
1811 | if (schema == PBES2) | ||
1812 | { | ||
1813 | if ((result = | ||
1814 | asn1_create_element (_gnutls_get_pkix (), | ||
1815 | "PKIX1.pkcs-5-PBES2-params", | ||
1816 | &pbes2_asn)) != ASN1_SUCCESS) | ||
1817 | { | ||
1818 | gnutls_assert (); | ||
1819 | return _gnutls_asn2err (result); | ||
1820 | } | ||
1821 | |||
1822 | result = write_pbkdf2_params (pbes2_asn, kdf_params); | ||
1823 | if (result < 0) | ||
1824 | { | ||
1825 | gnutls_assert (); | ||
1826 | goto error; | ||
1827 | } | ||
1828 | |||
1829 | result = write_pbe_enc_params (pbes2_asn, enc_params); | ||
1830 | if (result < 0) | ||
1831 | { | ||
1832 | gnutls_assert (); | ||
1833 | goto error; | ||
1834 | } | ||
1835 | |||
1836 | result = _gnutls_x509_der_encode_and_copy (pbes2_asn, "", | ||
1837 | pkcs8_asn, where, 0); | ||
1838 | if (result < 0) | ||
1839 | { | ||
1840 | gnutls_assert (); | ||
1841 | goto error; | ||
1842 | } | ||
1843 | |||
1844 | asn1_delete_structure (&pbes2_asn); | ||
1845 | } | ||
1846 | else | ||
1847 | { /* PKCS12 schemas */ | ||
1848 | |||
1849 | if ((result = | ||
1850 | asn1_create_element (_gnutls_get_pkix (), | ||
1851 | "PKIX1.pkcs-12-PbeParams", | ||
1852 | &pbes2_asn)) != ASN1_SUCCESS) | ||
1853 | { | ||
1854 | gnutls_assert (); | ||
1855 | result = _gnutls_asn2err (result); | ||
1856 | goto error; | ||
1857 | } | ||
1858 | |||
1859 | result = write_pkcs12_kdf_params (pbes2_asn, kdf_params); | ||
1860 | if (result < 0) | ||
1861 | { | ||
1862 | gnutls_assert (); | ||
1863 | goto error; | ||
1864 | } | ||
1865 | |||
1866 | result = _gnutls_x509_der_encode_and_copy (pbes2_asn, "", | ||
1867 | pkcs8_asn, where, 0); | ||
1868 | if (result < 0) | ||
1869 | { | ||
1870 | gnutls_assert (); | ||
1871 | goto error; | ||
1872 | } | ||
1873 | |||
1874 | asn1_delete_structure (&pbes2_asn); | ||
1875 | |||
1876 | } | ||
1877 | |||
1878 | return 0; | ||
1879 | |||
1880 | error: | ||
1881 | asn1_delete_structure (&pbes2_asn); | ||
1882 | return result; | ||
1883 | |||
1884 | } | ||
1885 | |||
1886 | static int | ||
1887 | encrypt_data (const gnutls_datum_t * plain, | ||
1888 | const struct pbe_enc_params *enc_params, | ||
1889 | gnutls_datum_t * key, gnutls_datum_t * encrypted) | ||
1890 | { | ||
1891 | int result; | ||
1892 | int data_size; | ||
1893 | opaque *data = NULL; | ||
1894 | gnutls_datum_t d_iv; | ||
1895 | cipher_hd_t ch = NULL; | ||
1896 | opaque pad, pad_size; | ||
1897 | |||
1898 | pad_size = _gnutls_cipher_get_block_size (enc_params->cipher); | ||
1899 | |||
1900 | if (pad_size == 1) /* stream */ | ||
1901 | pad_size = 0; | ||
1902 | |||
1903 | data = gnutls_malloc (plain->size + pad_size); | ||
1904 | if (data == NULL) | ||
1905 | { | ||
1906 | gnutls_assert (); | ||
1907 | return GNUTLS_E_MEMORY_ERROR; | ||
1908 | } | ||
1909 | |||
1910 | memcpy (data, plain->data, plain->size); | ||
1911 | |||
1912 | if (pad_size> 0) | ||
1913 | { | ||
1914 | pad = pad_size - (plain->size % pad_size); | ||
1915 | if (pad == 0) | ||
1916 | pad = pad_size; | ||
1917 | memset (&data[plain->size], pad, pad); | ||
1918 | } | ||
1919 | else | ||
1920 | pad = 0; | ||
1921 | |||
1922 | data_size = plain->size + pad; | ||
1923 | |||
1924 | d_iv.data = (opaque *) enc_params->iv; | ||
1925 | d_iv.size = enc_params->iv_size; | ||
1926 | ch = _gnutls_cipher_init (enc_params->cipher, key, &d_iv); | ||
1927 | |||
1928 | if (ch == GNUTLS_CIPHER_FAILED) | ||
1929 | { | ||
1930 | gnutls_assert (); | ||
1931 | result = GNUTLS_E_ENCRYPTION_FAILED; | ||
1932 | goto error; | ||
1933 | } | ||
1934 | |||
1935 | result = _gnutls_cipher_encrypt (ch, data, data_size); | ||
1936 | if (result < 0) | ||
1937 | { | ||
1938 | gnutls_assert (); | ||
1939 | goto error; | ||
1940 | } | ||
1941 | |||
1942 | encrypted->data = data; | ||
1943 | encrypted->size = data_size; | ||
1944 | |||
1945 | _gnutls_cipher_deinit (ch); | ||
1946 | |||
1947 | return 0; | ||
1948 | |||
1949 | error: | ||
1950 | gnutls_free (data); | ||
1951 | if (ch != NULL) | ||
1952 | _gnutls_cipher_deinit (ch); | ||
1953 | return result; | ||
1954 | } | ||
1955 | |||
1956 | /* Decrypts a PKCS #7 encryptedData. The output is allocated | ||
1957 | * and stored in dec. | ||
1958 | */ | ||
1959 | int | ||
1960 | _gnutls_pkcs7_decrypt_data (const gnutls_datum_t * data, | ||
1961 | const char *password, gnutls_datum_t * dec) | ||
1962 | { | ||
1963 | int result, len; | ||
1964 | char enc_oid[64]; | ||
1965 | gnutls_datum_t tmp; | ||
1966 | ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY, pkcs7_asn = ASN1_TYPE_EMPTY; | ||
1967 | int params_start, params_end, params_len; | ||
1968 | struct pbkdf2_params kdf_params; | ||
1969 | struct pbe_enc_params enc_params; | ||
1970 | schema_id schema; | ||
1971 | |||
1972 | if ((result = | ||
1973 | asn1_create_element (_gnutls_get_pkix (), | ||
1974 | "PKIX1.pkcs-7-EncryptedData", | ||
1975 | &pkcs7_asn)) != ASN1_SUCCESS) | ||
1976 | { | ||
1977 | gnutls_assert (); | ||
1978 | result = _gnutls_asn2err (result); | ||
1979 | goto error; | ||
1980 | } | ||
1981 | |||
1982 | result = asn1_der_decoding (&pkcs7_asn, data->data, data->size, NULL); | ||
1983 | if (result != ASN1_SUCCESS) | ||
1984 | { | ||
1985 | gnutls_assert (); | ||
1986 | result = _gnutls_asn2err (result); | ||
1987 | goto error; | ||
1988 | } | ||
1989 | |||
1990 | /* Check the encryption schema OID | ||
1991 | */ | ||
1992 | len = sizeof (enc_oid); | ||
1993 | result = | ||
1994 | asn1_read_value (pkcs7_asn, | ||
1995 | "encryptedContentInfo.contentEncryptionAlgorithm.algorithm", | ||
1996 | enc_oid, &len); | ||
1997 | if (result != ASN1_SUCCESS) | ||
1998 | { | ||
1999 | gnutls_assert (); | ||
2000 | result = _gnutls_asn2err (result); | ||
2001 | goto error; | ||
2002 | } | ||
2003 | |||
2004 | if ((result = check_schema (enc_oid)) < 0) | ||
2005 | { | ||
2006 | gnutls_assert (); | ||
2007 | goto error; | ||
2008 | } | ||
2009 | schema = result; | ||
2010 | |||
2011 | /* Get the DER encoding of the parameters. | ||
2012 | */ | ||
2013 | result = | ||
2014 | asn1_der_decoding_startEnd (pkcs7_asn, data->data, data->size, | ||
2015 | "encryptedContentInfo.contentEncryptionAlgorithm.parameters", | ||
2016 | ¶ms_start, ¶ms_end); | ||
2017 | if (result != ASN1_SUCCESS) | ||
2018 | { | ||
2019 | gnutls_assert (); | ||
2020 | result = _gnutls_asn2err (result); | ||
2021 | goto error; | ||
2022 | } | ||
2023 | params_len = params_end - params_start + 1; | ||
2024 | |||
2025 | result = | ||
2026 | read_pkcs_schema_params (schema, password, | ||
2027 | &data->data[params_start], | ||
2028 | params_len, &kdf_params, &enc_params); | ||
2029 | if (result < ASN1_SUCCESS) | ||
2030 | { | ||
2031 | gnutls_assert (); | ||
2032 | result = _gnutls_asn2err (result); | ||
2033 | goto error; | ||
2034 | } | ||
2035 | |||
2036 | /* Parameters have been decoded. Now | ||
2037 | * decrypt the EncryptedData. | ||
2038 | */ | ||
2039 | |||
2040 | result = | ||
2041 | decrypt_data (schema, pkcs7_asn, | ||
2042 | "encryptedContentInfo.encryptedContent", password, | ||
2043 | &kdf_params, &enc_params, &tmp); | ||
2044 | if (result < 0) | ||
2045 | { | ||
2046 | gnutls_assert (); | ||
2047 | goto error; | ||
2048 | } | ||
2049 | |||
2050 | asn1_delete_structure (&pkcs7_asn); | ||
2051 | |||
2052 | *dec = tmp; | ||
2053 | |||
2054 | return 0; | ||
2055 | |||
2056 | error: | ||
2057 | asn1_delete_structure (&pbes2_asn); | ||
2058 | asn1_delete_structure (&pkcs7_asn); | ||
2059 | return result; | ||
2060 | } | ||
2061 | |||
2062 | /* Encrypts to a PKCS #7 encryptedData. The output is allocated | ||
2063 | * and stored in enc. | ||
2064 | */ | ||
2065 | int | ||
2066 | _gnutls_pkcs7_encrypt_data (schema_id schema, | ||
2067 | const gnutls_datum_t * data, | ||
2068 | const char *password, gnutls_datum_t * enc) | ||
2069 | { | ||
2070 | int result; | ||
2071 | gnutls_datum_t key = | ||
2072 | { NULL, 0}; | ||
2073 | gnutls_datum_t tmp = | ||
2074 | { NULL, 0}; | ||
2075 | ASN1_TYPE pkcs7_asn = ASN1_TYPE_EMPTY; | ||
2076 | struct pbkdf2_params kdf_params; | ||
2077 | struct pbe_enc_params enc_params; | ||
2078 | |||
2079 | if ((result = | ||
2080 | asn1_create_element (_gnutls_get_pkix (), | ||
2081 | "PKIX1.pkcs-7-EncryptedData", | ||
2082 | &pkcs7_asn)) != ASN1_SUCCESS) | ||
2083 | { | ||
2084 | gnutls_assert (); | ||
2085 | result = _gnutls_asn2err (result); | ||
2086 | goto error; | ||
2087 | } | ||
2088 | |||
2089 | /* Write the encryption schema OID | ||
2090 | */ | ||
2091 | switch (schema) | ||
2092 | { | ||
2093 | case PBES2: | ||
2094 | result = | ||
2095 | asn1_write_value (pkcs7_asn, | ||
2096 | "encryptedContentInfo.contentEncryptionAlgorithm.algorithm", | ||
2097 | PBES2_OID, 1); | ||
2098 | break; | ||
2099 | case PKCS12_3DES_SHA1: | ||
2100 | result = | ||
2101 | asn1_write_value (pkcs7_asn, | ||
2102 | "encryptedContentInfo.contentEncryptionAlgorithm.algorithm", | ||
2103 | PKCS12_PBE_3DES_SHA1_OID, 1); | ||
2104 | break; | ||
2105 | case PKCS12_ARCFOUR_SHA1: | ||
2106 | result = | ||
2107 | asn1_write_value (pkcs7_asn, | ||
2108 | "encryptedContentInfo.contentEncryptionAlgorithm.algorithm", | ||
2109 | PKCS12_PBE_ARCFOUR_SHA1_OID, 1); | ||
2110 | break; | ||
2111 | case PKCS12_RC2_40_SHA1: | ||
2112 | result = | ||
2113 | asn1_write_value (pkcs7_asn, | ||
2114 | "encryptedContentInfo.contentEncryptionAlgorithm.algorithm", | ||
2115 | PKCS12_PBE_RC2_40_SHA1_OID, 1); | ||
2116 | break; | ||
2117 | |||
2118 | } | ||
2119 | |||
2120 | if (result != ASN1_SUCCESS) | ||
2121 | { | ||
2122 | gnutls_assert (); | ||
2123 | result = _gnutls_asn2err (result); | ||
2124 | goto error; | ||
2125 | } | ||
2126 | |||
2127 | /* Generate a symmetric key. | ||
2128 | */ | ||
2129 | |||
2130 | result = generate_key (schema, password, &kdf_params, &enc_params, &key); | ||
2131 | if (result < 0) | ||
2132 | { | ||
2133 | gnutls_assert (); | ||
2134 | goto error; | ||
2135 | } | ||
2136 | |||
2137 | result = write_schema_params (schema, pkcs7_asn, | ||
2138 | "encryptedContentInfo.contentEncryptionAlgorithm.parameters", | ||
2139 | &kdf_params, &enc_params); | ||
2140 | if (result < 0) | ||
2141 | { | ||
2142 | gnutls_assert (); | ||
2143 | goto error; | ||
2144 | } | ||
2145 | |||
2146 | /* Parameters have been encoded. Now | ||
2147 | * encrypt the Data. | ||
2148 | */ | ||
2149 | result = encrypt_data (data, &enc_params, &key, &tmp); | ||
2150 | if (result < 0) | ||
2151 | { | ||
2152 | gnutls_assert (); | ||
2153 | goto error; | ||
2154 | } | ||
2155 | |||
2156 | /* write the encrypted data. | ||
2157 | */ | ||
2158 | result = | ||
2159 | asn1_write_value (pkcs7_asn, | ||
2160 | "encryptedContentInfo.encryptedContent", tmp.data, | ||
2161 | tmp.size); | ||
2162 | if (result != ASN1_SUCCESS) | ||
2163 | { | ||
2164 | gnutls_assert (); | ||
2165 | result = _gnutls_asn2err (result); | ||
2166 | goto error; | ||
2167 | } | ||
2168 | |||
2169 | _gnutls_free_datum (&tmp); | ||
2170 | _gnutls_free_datum (&key); | ||
2171 | |||
2172 | /* Now write the rest of the pkcs-7 stuff. | ||
2173 | */ | ||
2174 | |||
2175 | result = _gnutls_x509_write_uint32 (pkcs7_asn, "version", 0); | ||
2176 | if (result < 0) | ||
2177 | { | ||
2178 | gnutls_assert (); | ||
2179 | goto error; | ||
2180 | } | ||
2181 | |||
2182 | result = | ||
2183 | asn1_write_value (pkcs7_asn, "encryptedContentInfo.contentType", | ||
2184 | DATA_OID, 1); | ||
2185 | if (result != ASN1_SUCCESS) | ||
2186 | { | ||
2187 | gnutls_assert (); | ||
2188 | result = _gnutls_asn2err (result); | ||
2189 | goto error; | ||
2190 | } | ||
2191 | |||
2192 | result = asn1_write_value (pkcs7_asn, "unprotectedAttrs", NULL, 0); | ||
2193 | if (result != ASN1_SUCCESS) | ||
2194 | { | ||
2195 | gnutls_assert (); | ||
2196 | result = _gnutls_asn2err (result); | ||
2197 | goto error; | ||
2198 | } | ||
2199 | |||
2200 | /* Now encode and copy the DER stuff. | ||
2201 | */ | ||
2202 | result = _gnutls_x509_der_encode (pkcs7_asn, "", enc, 0); | ||
2203 | |||
2204 | asn1_delete_structure (&pkcs7_asn); | ||
2205 | |||
2206 | if (result < 0) | ||
2207 | { | ||
2208 | gnutls_assert (); | ||
2209 | goto error; | ||
2210 | } | ||
2211 | |||
2212 | error: | ||
2213 | _gnutls_free_datum (&key); | ||
2214 | _gnutls_free_datum (&tmp); | ||
2215 | asn1_delete_structure (&pkcs7_asn); | ||
2216 | return result; | ||
2217 | } | ||
2218 | |||
2219 | #endif | ||
diff --git a/src/daemon/https/x509/rfc2818.h b/src/daemon/https/x509/rfc2818.h new file mode 100644 index 00000000..c3399145 --- /dev/null +++ b/src/daemon/https/x509/rfc2818.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | int _gnutls_hostname_compare (const char *certname, const char *hostname); | ||
26 | #define MAX_CN 256 | ||
diff --git a/src/daemon/https/x509/rfc2818_hostname.c b/src/daemon/https/x509/rfc2818_hostname.c new file mode 100644 index 00000000..93a96589 --- /dev/null +++ b/src/daemon/https/x509/rfc2818_hostname.c | |||
@@ -0,0 +1,160 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation | ||
3 | * Copyright (C) 2002 Andrew McDonald | ||
4 | * | ||
5 | * This file is part of GNUTLS. | ||
6 | * | ||
7 | * The GNUTLS library is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU Lesser General Public License | ||
9 | * as published by the Free Software Foundation; either version 2.1 of | ||
10 | * the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This library is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public | ||
18 | * License along with this library; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
20 | * USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <gnutls_int.h> | ||
25 | #include <x509.h> | ||
26 | #include <dn.h> | ||
27 | #include <common.h> | ||
28 | #include <rfc2818.h> | ||
29 | #include <gnutls_errors.h> | ||
30 | |||
31 | /* compare hostname against certificate, taking account of wildcards | ||
32 | * return 1 on success or 0 on error | ||
33 | */ | ||
34 | int | ||
35 | _gnutls_hostname_compare (const char *certname, const char *hostname) | ||
36 | { | ||
37 | const char *cmpstr1, *cmpstr2; | ||
38 | |||
39 | if (strlen (certname) == 0 || strlen (hostname) == 0) | ||
40 | return 0; | ||
41 | |||
42 | if (strlen (certname) > 2 && strncmp (certname, "*.", 2) == 0) | ||
43 | { | ||
44 | /* a wildcard certificate */ | ||
45 | |||
46 | cmpstr1 = certname + 1; | ||
47 | |||
48 | /* find the first dot in hostname, compare from there on */ | ||
49 | cmpstr2 = strchr (hostname, '.'); | ||
50 | |||
51 | if (cmpstr2 == NULL) | ||
52 | { | ||
53 | /* error, the hostname we're connecting to is only a local part */ | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | if (strcasecmp (cmpstr1, cmpstr2) == 0) | ||
58 | { | ||
59 | return 1; | ||
60 | } | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | if (strcasecmp (certname, hostname) == 0) | ||
66 | { | ||
67 | return 1; | ||
68 | } | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * gnutls_x509_crt_check_hostname - This function compares the given hostname with the hostname in the certificate | ||
75 | * @cert: should contain an gnutls_x509_crt_t structure | ||
76 | * @hostname: A null terminated string that contains a DNS name | ||
77 | * | ||
78 | * This function will check if the given certificate's subject | ||
79 | * matches the given hostname. This is a basic implementation of the | ||
80 | * matching described in RFC2818 (HTTPS), which takes into account | ||
81 | * wildcards, and the DNSName/IPAddress subject alternative name PKIX | ||
82 | * extension. | ||
83 | * | ||
84 | * Returns non zero for a successful match, and zero on failure. | ||
85 | **/ | ||
86 | int | ||
87 | gnutls_x509_crt_check_hostname (gnutls_x509_crt_t cert, const char *hostname) | ||
88 | { | ||
89 | |||
90 | char dnsname[MAX_CN]; | ||
91 | size_t dnsnamesize; | ||
92 | int found_dnsname = 0; | ||
93 | int ret = 0; | ||
94 | int i = 0; | ||
95 | |||
96 | /* try matching against: | ||
97 | * 1) a DNS name as an alternative name (subjectAltName) extension | ||
98 | * in the certificate | ||
99 | * 2) the common name (CN) in the certificate | ||
100 | * | ||
101 | * either of these may be of the form: *.domain.tld | ||
102 | * | ||
103 | * only try (2) if there is no subjectAltName extension of | ||
104 | * type dNSName | ||
105 | */ | ||
106 | |||
107 | /* Check through all included subjectAltName extensions, comparing | ||
108 | * against all those of type dNSName. | ||
109 | */ | ||
110 | for (i = 0; !(ret < 0); i++) | ||
111 | { | ||
112 | |||
113 | dnsnamesize = sizeof (dnsname); | ||
114 | ret = gnutls_x509_crt_get_subject_alt_name (cert, i, | ||
115 | dnsname, &dnsnamesize, | ||
116 | NULL); | ||
117 | |||
118 | if (ret == GNUTLS_SAN_DNSNAME) | ||
119 | { | ||
120 | found_dnsname = 1; | ||
121 | if (_gnutls_hostname_compare (dnsname, hostname)) | ||
122 | { | ||
123 | return 1; | ||
124 | } | ||
125 | } | ||
126 | else if (ret == GNUTLS_SAN_IPADDRESS) | ||
127 | { | ||
128 | found_dnsname = 1; /* RFC 2818 is unclear whether the CN | ||
129 | should be compared for IP addresses | ||
130 | too, but we won't do it. */ | ||
131 | if (_gnutls_hostname_compare (dnsname, hostname)) | ||
132 | { | ||
133 | return 1; | ||
134 | } | ||
135 | } | ||
136 | } | ||
137 | |||
138 | if (!found_dnsname) | ||
139 | { | ||
140 | /* not got the necessary extension, use CN instead | ||
141 | */ | ||
142 | dnsnamesize = sizeof (dnsname); | ||
143 | if (gnutls_x509_crt_get_dn_by_oid (cert, OID_X520_COMMON_NAME, 0, | ||
144 | 0, dnsname, &dnsnamesize) < 0) | ||
145 | { | ||
146 | /* got an error, can't find a name | ||
147 | */ | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | if (_gnutls_hostname_compare (dnsname, hostname)) | ||
152 | { | ||
153 | return 1; | ||
154 | } | ||
155 | } | ||
156 | |||
157 | /* not found a matching name | ||
158 | */ | ||
159 | return 0; | ||
160 | } | ||
diff --git a/src/daemon/https/x509/sign.c b/src/daemon/https/x509/sign.c new file mode 100644 index 00000000..275fc3f7 --- /dev/null +++ b/src/daemon/https/x509/sign.c | |||
@@ -0,0 +1,346 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | /* All functions which relate to X.509 certificate signing stuff are | ||
26 | * included here | ||
27 | */ | ||
28 | |||
29 | #include <gnutls_int.h> | ||
30 | |||
31 | #ifdef ENABLE_PKI | ||
32 | |||
33 | #include <gnutls_errors.h> | ||
34 | #include <gnutls_cert.h> | ||
35 | #include <libtasn1.h> | ||
36 | #include <gnutls_global.h> | ||
37 | #include <gnutls_num.h> /* MAX */ | ||
38 | #include <gnutls_sig.h> | ||
39 | #include <gnutls_str.h> | ||
40 | #include <gnutls_datum.h> | ||
41 | #include <dn.h> | ||
42 | #include <x509.h> | ||
43 | #include <mpi.h> | ||
44 | #include <sign.h> | ||
45 | #include <common.h> | ||
46 | #include <verify.h> | ||
47 | |||
48 | /* Writes the digest information and the digest in a DER encoded | ||
49 | * structure. The digest info is allocated and stored into the info structure. | ||
50 | */ | ||
51 | static int | ||
52 | encode_ber_digest_info (gnutls_digest_algorithm_t hash, | ||
53 | const gnutls_datum_t * digest, gnutls_datum_t * info) | ||
54 | { | ||
55 | ASN1_TYPE dinfo = ASN1_TYPE_EMPTY; | ||
56 | int result; | ||
57 | const char *algo; | ||
58 | |||
59 | algo = _gnutls_x509_mac_to_oid ((gnutls_mac_algorithm_t) hash); | ||
60 | if (algo == NULL) | ||
61 | { | ||
62 | gnutls_assert (); | ||
63 | _gnutls_x509_log ("Hash algorithm: %d\n", hash); | ||
64 | return GNUTLS_E_UNKNOWN_PK_ALGORITHM; | ||
65 | } | ||
66 | |||
67 | if ((result = asn1_create_element (_gnutls_get_gnutls_asn (), | ||
68 | "GNUTLS.DigestInfo", | ||
69 | &dinfo)) != ASN1_SUCCESS) | ||
70 | { | ||
71 | gnutls_assert (); | ||
72 | return _gnutls_asn2err (result); | ||
73 | } | ||
74 | |||
75 | result = asn1_write_value (dinfo, "digestAlgorithm.algorithm", algo, 1); | ||
76 | if (result != ASN1_SUCCESS) | ||
77 | { | ||
78 | gnutls_assert (); | ||
79 | asn1_delete_structure (&dinfo); | ||
80 | return _gnutls_asn2err (result); | ||
81 | } | ||
82 | |||
83 | /* Write an ASN.1 NULL in the parameters field. This matches RFC | ||
84 | 3279 and RFC 4055, although is arguable incorrect from a historic | ||
85 | perspective (see those documents for more information). | ||
86 | Regardless of what is correct, this appears to be what most | ||
87 | implementations do. */ | ||
88 | result = asn1_write_value (dinfo, "digestAlgorithm.parameters", | ||
89 | "\x05\x00", 2); | ||
90 | if (result != ASN1_SUCCESS) | ||
91 | { | ||
92 | gnutls_assert (); | ||
93 | asn1_delete_structure (&dinfo); | ||
94 | return _gnutls_asn2err (result); | ||
95 | } | ||
96 | |||
97 | result = asn1_write_value (dinfo, "digest", digest->data, digest->size); | ||
98 | if (result != ASN1_SUCCESS) | ||
99 | { | ||
100 | gnutls_assert (); | ||
101 | asn1_delete_structure (&dinfo); | ||
102 | return _gnutls_asn2err (result); | ||
103 | } | ||
104 | |||
105 | info->size = 0; | ||
106 | asn1_der_coding (dinfo, "", NULL, &info->size, NULL); | ||
107 | |||
108 | info->data = gnutls_malloc (info->size); | ||
109 | if (info->data == NULL) | ||
110 | { | ||
111 | gnutls_assert (); | ||
112 | asn1_delete_structure (&dinfo); | ||
113 | return GNUTLS_E_MEMORY_ERROR; | ||
114 | } | ||
115 | |||
116 | result = asn1_der_coding (dinfo, "", info->data, &info->size, NULL); | ||
117 | if (result != ASN1_SUCCESS) | ||
118 | { | ||
119 | gnutls_assert (); | ||
120 | asn1_delete_structure (&dinfo); | ||
121 | return _gnutls_asn2err (result); | ||
122 | } | ||
123 | |||
124 | asn1_delete_structure (&dinfo); | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | /* if hash==MD5 then we do RSA-MD5 | ||
130 | * if hash==SHA then we do RSA-SHA | ||
131 | * params[0] is modulus | ||
132 | * params[1] is public key | ||
133 | */ | ||
134 | static int | ||
135 | pkcs1_rsa_sign (gnutls_digest_algorithm_t hash, const gnutls_datum_t * text, | ||
136 | mpi_t * params, int params_len, gnutls_datum_t * signature) | ||
137 | { | ||
138 | int ret; | ||
139 | opaque _digest[MAX_HASH_SIZE]; | ||
140 | GNUTLS_HASH_HANDLE hd; | ||
141 | gnutls_datum_t digest, info; | ||
142 | |||
143 | hd = _gnutls_hash_init (HASH2MAC (hash)); | ||
144 | if (hd == NULL) | ||
145 | { | ||
146 | gnutls_assert (); | ||
147 | return GNUTLS_E_HASH_FAILED; | ||
148 | } | ||
149 | |||
150 | _gnutls_hash (hd, text->data, text->size); | ||
151 | _gnutls_hash_deinit (hd, _digest); | ||
152 | |||
153 | digest.data = _digest; | ||
154 | digest.size = _gnutls_hash_get_algo_len (HASH2MAC (hash)); | ||
155 | |||
156 | /* Encode the digest as a DigestInfo | ||
157 | */ | ||
158 | if ((ret = encode_ber_digest_info (hash, &digest, &info)) != 0) | ||
159 | { | ||
160 | gnutls_assert (); | ||
161 | return ret; | ||
162 | } | ||
163 | |||
164 | if ((ret = | ||
165 | _gnutls_sign (GNUTLS_PK_RSA, params, params_len, &info, | ||
166 | signature)) < 0) | ||
167 | { | ||
168 | gnutls_assert (); | ||
169 | _gnutls_free_datum (&info); | ||
170 | return ret; | ||
171 | } | ||
172 | |||
173 | _gnutls_free_datum (&info); | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | /* Signs the given data using the parameters from the signer's | ||
179 | * private key. | ||
180 | * | ||
181 | * returns 0 on success. | ||
182 | * | ||
183 | * 'tbs' is the data to be signed | ||
184 | * 'signature' will hold the signature! | ||
185 | * 'hash' is only used in PKCS1 RSA signing. | ||
186 | */ | ||
187 | int | ||
188 | _gnutls_x509_sign (const gnutls_datum_t * tbs, | ||
189 | gnutls_digest_algorithm_t hash, | ||
190 | gnutls_x509_privkey_t signer, gnutls_datum_t * signature) | ||
191 | { | ||
192 | int ret; | ||
193 | |||
194 | switch (signer->pk_algorithm) | ||
195 | { | ||
196 | case GNUTLS_PK_RSA: | ||
197 | ret = | ||
198 | pkcs1_rsa_sign (hash, tbs, signer->params, signer->params_size, | ||
199 | signature); | ||
200 | if (ret < 0) | ||
201 | { | ||
202 | gnutls_assert (); | ||
203 | return ret; | ||
204 | } | ||
205 | return 0; | ||
206 | break; | ||
207 | default: | ||
208 | gnutls_assert (); | ||
209 | return GNUTLS_E_INTERNAL_ERROR; | ||
210 | } | ||
211 | |||
212 | } | ||
213 | |||
214 | /* This is the same as the _gnutls_x509_sign, but this one will decode | ||
215 | * the ASN1_TYPE given, and sign the DER data. Actually used to get the DER | ||
216 | * of the TBS and sign it on the fly. | ||
217 | */ | ||
218 | int | ||
219 | _gnutls_x509_sign_tbs (ASN1_TYPE cert, const char *tbs_name, | ||
220 | gnutls_digest_algorithm_t hash, | ||
221 | gnutls_x509_privkey_t signer, | ||
222 | gnutls_datum_t * signature) | ||
223 | { | ||
224 | int result; | ||
225 | opaque *buf; | ||
226 | int buf_size; | ||
227 | gnutls_datum_t tbs; | ||
228 | |||
229 | buf_size = 0; | ||
230 | asn1_der_coding (cert, tbs_name, NULL, &buf_size, NULL); | ||
231 | |||
232 | buf = gnutls_alloca (buf_size); | ||
233 | if (buf == NULL) | ||
234 | { | ||
235 | gnutls_assert (); | ||
236 | return GNUTLS_E_MEMORY_ERROR; | ||
237 | } | ||
238 | |||
239 | result = asn1_der_coding (cert, tbs_name, buf, &buf_size, NULL); | ||
240 | |||
241 | if (result != ASN1_SUCCESS) | ||
242 | { | ||
243 | gnutls_assert (); | ||
244 | gnutls_afree (buf); | ||
245 | return _gnutls_asn2err (result); | ||
246 | } | ||
247 | |||
248 | tbs.data = buf; | ||
249 | tbs.size = buf_size; | ||
250 | |||
251 | result = _gnutls_x509_sign (&tbs, hash, signer, signature); | ||
252 | gnutls_afree (buf); | ||
253 | |||
254 | return result; | ||
255 | } | ||
256 | |||
257 | /*- | ||
258 | * _gnutls_x509_pkix_sign - This function will sign a CRL or a certificate with a key | ||
259 | * @src: should contain an ASN1_TYPE | ||
260 | * @issuer: is the certificate of the certificate issuer | ||
261 | * @issuer_key: holds the issuer's private key | ||
262 | * | ||
263 | * This function will sign a CRL or a certificate with the issuer's private key, and | ||
264 | * will copy the issuer's information into the CRL or certificate. | ||
265 | * | ||
266 | * Returns 0 on success. | ||
267 | * | ||
268 | -*/ | ||
269 | int | ||
270 | _gnutls_x509_pkix_sign (ASN1_TYPE src, const char *src_name, | ||
271 | gnutls_digest_algorithm_t dig, | ||
272 | gnutls_x509_crt_t issuer, | ||
273 | gnutls_x509_privkey_t issuer_key) | ||
274 | { | ||
275 | int result; | ||
276 | gnutls_datum_t signature; | ||
277 | char name[128]; | ||
278 | |||
279 | /* Step 1. Copy the issuer's name into the certificate. | ||
280 | */ | ||
281 | _gnutls_str_cpy (name, sizeof (name), src_name); | ||
282 | _gnutls_str_cat (name, sizeof (name), ".issuer"); | ||
283 | |||
284 | result = asn1_copy_node (src, name, issuer->cert, "tbsCertificate.subject"); | ||
285 | if (result != ASN1_SUCCESS) | ||
286 | { | ||
287 | gnutls_assert (); | ||
288 | return _gnutls_asn2err (result); | ||
289 | } | ||
290 | |||
291 | /* Step 1.5. Write the signature stuff in the tbsCertificate. | ||
292 | */ | ||
293 | _gnutls_str_cpy (name, sizeof (name), src_name); | ||
294 | _gnutls_str_cat (name, sizeof (name), ".signature"); | ||
295 | |||
296 | result = _gnutls_x509_write_sig_params (src, name, | ||
297 | issuer_key->pk_algorithm, dig, | ||
298 | issuer_key->params, | ||
299 | issuer_key->params_size); | ||
300 | if (result < 0) | ||
301 | { | ||
302 | gnutls_assert (); | ||
303 | return result; | ||
304 | } | ||
305 | |||
306 | /* Step 2. Sign the certificate. | ||
307 | */ | ||
308 | result = _gnutls_x509_sign_tbs (src, src_name, dig, issuer_key, &signature); | ||
309 | |||
310 | if (result < 0) | ||
311 | { | ||
312 | gnutls_assert (); | ||
313 | return result; | ||
314 | } | ||
315 | |||
316 | /* write the signature (bits) | ||
317 | */ | ||
318 | result = | ||
319 | asn1_write_value (src, "signature", signature.data, signature.size * 8); | ||
320 | |||
321 | _gnutls_free_datum (&signature); | ||
322 | |||
323 | if (result != ASN1_SUCCESS) | ||
324 | { | ||
325 | gnutls_assert (); | ||
326 | return _gnutls_asn2err (result); | ||
327 | } | ||
328 | |||
329 | /* Step 3. Move up and write the AlgorithmIdentifier, which is also | ||
330 | * the same. | ||
331 | */ | ||
332 | |||
333 | result = _gnutls_x509_write_sig_params (src, "signatureAlgorithm", | ||
334 | issuer_key->pk_algorithm, dig, | ||
335 | issuer_key->params, | ||
336 | issuer_key->params_size); | ||
337 | if (result < 0) | ||
338 | { | ||
339 | gnutls_assert (); | ||
340 | return result; | ||
341 | } | ||
342 | |||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | #endif | ||
diff --git a/src/daemon/https/x509/sign.h b/src/daemon/https/x509/sign.h new file mode 100644 index 00000000..e1bf46d4 --- /dev/null +++ b/src/daemon/https/x509/sign.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | int _gnutls_x509_sign (const gnutls_datum_t * tbs, | ||
26 | gnutls_digest_algorithm_t hash, | ||
27 | gnutls_x509_privkey_t signer, | ||
28 | gnutls_datum_t * signature); | ||
29 | int _gnutls_x509_sign_tbs (ASN1_TYPE cert, const char *tbs_name, | ||
30 | gnutls_digest_algorithm_t hash, | ||
31 | gnutls_x509_privkey_t signer, | ||
32 | gnutls_datum_t * signature); | ||
33 | int _gnutls_x509_pkix_sign (ASN1_TYPE src, const char *src_name, | ||
34 | gnutls_digest_algorithm_t, | ||
35 | gnutls_x509_crt_t issuer, | ||
36 | gnutls_x509_privkey_t issuer_key); | ||
diff --git a/src/daemon/https/x509/verify.h b/src/daemon/https/x509/verify.h new file mode 100644 index 00000000..d7ca5151 --- /dev/null +++ b/src/daemon/https/x509/verify.h | |||
@@ -0,0 +1,34 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include "x509.h" | ||
26 | |||
27 | int gnutls_x509_crt_is_issuer (gnutls_x509_crt_t cert, | ||
28 | gnutls_x509_crt_t issuer); | ||
29 | int _gnutls_x509_verify_signature (const gnutls_datum_t * tbs, | ||
30 | const gnutls_datum_t * signature, | ||
31 | gnutls_x509_crt_t issuer); | ||
32 | int _gnutls_x509_privkey_verify_signature (const gnutls_datum_t * tbs, | ||
33 | const gnutls_datum_t * signature, | ||
34 | gnutls_x509_privkey_t issuer); | ||
diff --git a/src/daemon/https/x509/x509-api.texi b/src/daemon/https/x509/x509-api.texi new file mode 100644 index 00000000..f4dd35b9 --- /dev/null +++ b/src/daemon/https/x509/x509-api.texi | |||
@@ -0,0 +1,2943 @@ | |||
1 | |||
2 | @subheading gnutls_x509_crl_init | ||
3 | @anchor{gnutls_x509_crl_init} | ||
4 | @deftypefun {int} {gnutls_x509_crl_init} (gnutls_x509_crl_t * @var{crl}) | ||
5 | @var{crl}: The structure to be initialized | ||
6 | |||
7 | This function will initialize a CRL structure. CRL stands for | ||
8 | Certificate Revocation List. A revocation list usually contains | ||
9 | lists of certificate serial numbers that have been revoked | ||
10 | by an Authority. The revocation lists are always signed with | ||
11 | the authority's private key. | ||
12 | |||
13 | Returns 0 on success. | ||
14 | @end deftypefun | ||
15 | |||
16 | @subheading gnutls_x509_crl_deinit | ||
17 | @anchor{gnutls_x509_crl_deinit} | ||
18 | @deftypefun {void} {gnutls_x509_crl_deinit} (gnutls_x509_crl_t @var{crl}) | ||
19 | @var{crl}: The structure to be initialized | ||
20 | |||
21 | This function will deinitialize a CRL structure. | ||
22 | @end deftypefun | ||
23 | |||
24 | @subheading gnutls_x509_crl_import | ||
25 | @anchor{gnutls_x509_crl_import} | ||
26 | @deftypefun {int} {gnutls_x509_crl_import} (gnutls_x509_crl_t @var{crl}, const gnutls_datum_t * @var{data}, gnutls_x509_crt_fmt_t @var{format}) | ||
27 | @var{crl}: The structure to store the parsed CRL. | ||
28 | |||
29 | @var{data}: The DER or PEM encoded CRL. | ||
30 | |||
31 | @var{format}: One of DER or PEM | ||
32 | |||
33 | This function will convert the given DER or PEM encoded CRL | ||
34 | to the native gnutls_x509_crl_t format. The output will be stored in 'crl'. | ||
35 | |||
36 | If the CRL is PEM encoded it should have a header of "X509 CRL". | ||
37 | |||
38 | Returns 0 on success. | ||
39 | @end deftypefun | ||
40 | |||
41 | @subheading gnutls_x509_crl_get_issuer_dn | ||
42 | @anchor{gnutls_x509_crl_get_issuer_dn} | ||
43 | @deftypefun {int} {gnutls_x509_crl_get_issuer_dn} (const gnutls_x509_crl_t @var{crl}, char * @var{buf}, size_t * @var{sizeof_buf}) | ||
44 | @var{crl}: should contain a gnutls_x509_crl_t structure | ||
45 | |||
46 | @var{buf}: a pointer to a structure to hold the peer's name (may be null) | ||
47 | |||
48 | @var{sizeof_buf}: initially holds the size of @code{buf} | ||
49 | |||
50 | This function will copy the name of the CRL issuer in the provided buffer. The name | ||
51 | will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253. The output | ||
52 | string will be ASCII or UTF-8 encoded, depending on the certificate data. | ||
53 | |||
54 | If buf is null then only the size will be filled. | ||
55 | |||
56 | Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not long enough, and | ||
57 | in that case the sizeof_buf will be updated with the required size, and | ||
58 | 0 on success. | ||
59 | @end deftypefun | ||
60 | |||
61 | @subheading gnutls_x509_crl_get_issuer_dn_by_oid | ||
62 | @anchor{gnutls_x509_crl_get_issuer_dn_by_oid} | ||
63 | @deftypefun {int} {gnutls_x509_crl_get_issuer_dn_by_oid} (gnutls_x509_crl_t @var{crl}, const char * @var{oid}, int @var{indx}, unsigned int @var{raw_flag}, void * @var{buf}, size_t * @var{sizeof_buf}) | ||
64 | @var{crl}: should contain a gnutls_x509_crl_t structure | ||
65 | |||
66 | @var{oid}: holds an Object Identified in null terminated string | ||
67 | |||
68 | @var{indx}: In case multiple same OIDs exist in the RDN, this specifies which to send. Use zero to get the first one. | ||
69 | |||
70 | @var{raw_flag}: If non zero returns the raw DER data of the DN part. | ||
71 | |||
72 | @var{buf}: a pointer to a structure to hold the peer's name (may be null) | ||
73 | |||
74 | @var{sizeof_buf}: initially holds the size of @code{buf} | ||
75 | |||
76 | This function will extract the part of the name of the CRL issuer specified | ||
77 | by the given OID. The output will be encoded as described in RFC2253. The output | ||
78 | string will be ASCII or UTF-8 encoded, depending on the certificate data. | ||
79 | |||
80 | Some helper macros with popular OIDs can be found in gnutls/x509.h | ||
81 | If raw flag is zero, this function will only return known OIDs as text. Other OIDs | ||
82 | will be DER encoded, as described in RFC2253 -- in hex format with a '\#' prefix. | ||
83 | You can check about known OIDs using @code{gnutls_x509_dn_oid_known()}. | ||
84 | |||
85 | If buf is null then only the size will be filled. | ||
86 | |||
87 | Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not long enough, and | ||
88 | in that case the sizeof_buf will be updated with the required size, | ||
89 | and 0 on success. | ||
90 | @end deftypefun | ||
91 | |||
92 | @subheading gnutls_x509_crl_get_dn_oid | ||
93 | @anchor{gnutls_x509_crl_get_dn_oid} | ||
94 | @deftypefun {int} {gnutls_x509_crl_get_dn_oid} (gnutls_x509_crl_t @var{crl}, int @var{indx}, void * @var{oid}, size_t * @var{sizeof_oid}) | ||
95 | @var{crl}: should contain a gnutls_x509_crl_t structure | ||
96 | |||
97 | @var{indx}: Specifies which DN OID to send. Use zero to get the first one. | ||
98 | |||
99 | @var{oid}: a pointer to a structure to hold the name (may be null) | ||
100 | |||
101 | @var{sizeof_oid}: initially holds the size of 'oid' | ||
102 | |||
103 | This function will extract the requested OID of the name of the CRL issuer, specified | ||
104 | by the given index. | ||
105 | |||
106 | If oid is null then only the size will be filled. | ||
107 | |||
108 | Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not long enough, and | ||
109 | in that case the sizeof_oid will be updated with the required size. | ||
110 | On success 0 is returned. | ||
111 | @end deftypefun | ||
112 | |||
113 | @subheading gnutls_x509_crl_get_signature_algorithm | ||
114 | @anchor{gnutls_x509_crl_get_signature_algorithm} | ||
115 | @deftypefun {int} {gnutls_x509_crl_get_signature_algorithm} (gnutls_x509_crl_t @var{crl}) | ||
116 | @var{crl}: should contain a gnutls_x509_crl_t structure | ||
117 | |||
118 | This function will return a value of the gnutls_sign_algorithm_t enumeration that | ||
119 | is the signature algorithm. | ||
120 | |||
121 | Returns a negative value on error. | ||
122 | @end deftypefun | ||
123 | |||
124 | @subheading gnutls_x509_crl_get_signature | ||
125 | @anchor{gnutls_x509_crl_get_signature} | ||
126 | @deftypefun {int} {gnutls_x509_crl_get_signature} (gnutls_x509_crl_t @var{crl}, char * @var{sig}, size_t * @var{sizeof_sig}) | ||
127 | @var{crl}: should contain a gnutls_x509_crl_t structure | ||
128 | |||
129 | @var{sig}: a pointer where the signature part will be copied (may be null). | ||
130 | |||
131 | @var{sizeof_sig}: initially holds the size of @code{sig} | ||
132 | |||
133 | This function will extract the signature field of a CRL. | ||
134 | |||
135 | Returns 0 on success, and a negative value on error. | ||
136 | @end deftypefun | ||
137 | |||
138 | @subheading gnutls_x509_crl_get_version | ||
139 | @anchor{gnutls_x509_crl_get_version} | ||
140 | @deftypefun {int} {gnutls_x509_crl_get_version} (gnutls_x509_crl_t @var{crl}) | ||
141 | @var{crl}: should contain a gnutls_x509_crl_t structure | ||
142 | |||
143 | This function will return the version of the specified CRL. | ||
144 | |||
145 | Returns a negative value on error. | ||
146 | @end deftypefun | ||
147 | |||
148 | @subheading gnutls_x509_crl_get_this_update | ||
149 | @anchor{gnutls_x509_crl_get_this_update} | ||
150 | @deftypefun {time_t} {gnutls_x509_crl_get_this_update} (gnutls_x509_crl_t @var{crl}) | ||
151 | @var{crl}: should contain a gnutls_x509_crl_t structure | ||
152 | |||
153 | This function will return the time this CRL was issued. | ||
154 | |||
155 | Returns (time_t)-1 on error. | ||
156 | @end deftypefun | ||
157 | |||
158 | @subheading gnutls_x509_crl_get_next_update | ||
159 | @anchor{gnutls_x509_crl_get_next_update} | ||
160 | @deftypefun {time_t} {gnutls_x509_crl_get_next_update} (gnutls_x509_crl_t @var{crl}) | ||
161 | @var{crl}: should contain a gnutls_x509_crl_t structure | ||
162 | |||
163 | This function will return the time the next CRL will be issued. | ||
164 | This field is optional in a CRL so it might be normal to get | ||
165 | an error instead. | ||
166 | |||
167 | Returns (time_t)-1 on error. | ||
168 | @end deftypefun | ||
169 | |||
170 | @subheading gnutls_x509_crl_get_crt_count | ||
171 | @anchor{gnutls_x509_crl_get_crt_count} | ||
172 | @deftypefun {int} {gnutls_x509_crl_get_crt_count} (gnutls_x509_crl_t @var{crl}) | ||
173 | @var{crl}: should contain a gnutls_x509_crl_t structure | ||
174 | |||
175 | This function will return the number of revoked certificates in the | ||
176 | given CRL. | ||
177 | |||
178 | Returns a negative value on failure. | ||
179 | @end deftypefun | ||
180 | |||
181 | @subheading gnutls_x509_crl_get_crt_serial | ||
182 | @anchor{gnutls_x509_crl_get_crt_serial} | ||
183 | @deftypefun {int} {gnutls_x509_crl_get_crt_serial} (gnutls_x509_crl_t @var{crl}, int @var{indx}, unsigned char * @var{serial}, size_t * @var{serial_size}, time_t * @var{t}) | ||
184 | @var{crl}: should contain a gnutls_x509_crl_t structure | ||
185 | |||
186 | @var{indx}: the index of the certificate to extract (starting from 0) | ||
187 | |||
188 | @var{serial}: where the serial number will be copied | ||
189 | |||
190 | @var{serial_size}: initially holds the size of serial | ||
191 | |||
192 | @var{t}: if non null, will hold the time this certificate was revoked | ||
193 | |||
194 | This function will return the serial number of the specified, by | ||
195 | the index, revoked certificate. | ||
196 | |||
197 | Returns a negative value on failure. | ||
198 | @end deftypefun | ||
199 | |||
200 | @subheading gnutls_x509_crl_export | ||
201 | @anchor{gnutls_x509_crl_export} | ||
202 | @deftypefun {int} {gnutls_x509_crl_export} (gnutls_x509_crl_t @var{crl}, gnutls_x509_crt_fmt_t @var{format}, void * @var{output_data}, size_t * @var{output_data_size}) | ||
203 | @var{crl}: Holds the revocation list | ||
204 | |||
205 | @var{format}: the format of output params. One of PEM or DER. | ||
206 | |||
207 | @var{output_data}: will contain a private key PEM or DER encoded | ||
208 | |||
209 | @var{output_data_size}: holds the size of output_data (and will be replaced by the actual size of parameters) | ||
210 | |||
211 | This function will export the revocation list to DER or PEM format. | ||
212 | |||
213 | If the buffer provided is not long enough to hold the output, then | ||
214 | GNUTLS_E_SHORT_MEMORY_BUFFER will be returned. | ||
215 | |||
216 | If the structure is PEM encoded, it will have a header | ||
217 | of "BEGIN X509 CRL". | ||
218 | |||
219 | Returns 0 on success, and a negative value on failure. | ||
220 | @end deftypefun | ||
221 | |||
222 | @subheading gnutls_x509_rdn_get | ||
223 | @anchor{gnutls_x509_rdn_get} | ||
224 | @deftypefun {int} {gnutls_x509_rdn_get} (const gnutls_datum_t * @var{idn}, char * @var{buf}, size_t * @var{sizeof_buf}) | ||
225 | @var{idn}: should contain a DER encoded RDN sequence | ||
226 | |||
227 | @var{buf}: a pointer to a structure to hold the peer's name | ||
228 | |||
229 | @var{sizeof_buf}: holds the size of @code{buf} | ||
230 | |||
231 | This function will return the name of the given RDN sequence. The | ||
232 | name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in | ||
233 | RFC2253. | ||
234 | |||
235 | If the provided buffer is not long enough, returns | ||
236 | GNUTLS_E_SHORT_MEMORY_BUFFER and *sizeof_buf will be updated. On | ||
237 | success 0 is returned. | ||
238 | @end deftypefun | ||
239 | |||
240 | @subheading gnutls_x509_rdn_get_by_oid | ||
241 | @anchor{gnutls_x509_rdn_get_by_oid} | ||
242 | @deftypefun {int} {gnutls_x509_rdn_get_by_oid} (const gnutls_datum_t * @var{idn}, const char * @var{oid}, int @var{indx}, unsigned int @var{raw_flag}, void * @var{buf}, size_t * @var{sizeof_buf}) | ||
243 | @var{idn}: should contain a DER encoded RDN sequence | ||
244 | |||
245 | @var{oid}: an Object Identifier | ||
246 | |||
247 | @var{indx}: In case multiple same OIDs exist in the RDN indicates which | ||
248 | to send. Use 0 for the first one. | ||
249 | |||
250 | @var{raw_flag}: If non zero then the raw DER data are returned. | ||
251 | |||
252 | @var{buf}: a pointer to a structure to hold the peer's name | ||
253 | |||
254 | @var{sizeof_buf}: holds the size of @code{buf} | ||
255 | |||
256 | This function will return the name of the given Object identifier, | ||
257 | of the RDN sequence. The name will be encoded using the rules | ||
258 | from RFC2253. | ||
259 | |||
260 | Returns GNUTLS_E_SHORT_MEMORY_BUFFER and updates *sizeof_buf if | ||
261 | the provided buffer is not long enough, and 0 on success. | ||
262 | @end deftypefun | ||
263 | |||
264 | @subheading gnutls_x509_rdn_get_oid | ||
265 | @anchor{gnutls_x509_rdn_get_oid} | ||
266 | @deftypefun {int} {gnutls_x509_rdn_get_oid} (const gnutls_datum_t * @var{idn}, int @var{indx}, void * @var{buf}, size_t * @var{sizeof_buf}) | ||
267 | @var{idn}: should contain a DER encoded RDN sequence | ||
268 | |||
269 | @var{indx}: Indicates which OID to return. Use 0 for the first one. | ||
270 | |||
271 | This function will return the specified Object identifier, of the | ||
272 | RDN sequence. | ||
273 | |||
274 | Returns GNUTLS_E_SHORT_MEMORY_BUFFER and updates *sizeof_buf if | ||
275 | the provided buffer is not long enough, and 0 on success. | ||
276 | @end deftypefun | ||
277 | |||
278 | @subheading gnutls_x509_dn_oid_known | ||
279 | @anchor{gnutls_x509_dn_oid_known} | ||
280 | @deftypefun {int} {gnutls_x509_dn_oid_known} (const char * @var{oid}) | ||
281 | @var{oid}: holds an Object Identifier in a null terminated string | ||
282 | |||
283 | This function will inform about known DN OIDs. This is useful since functions | ||
284 | like @code{gnutls_x509_crt_set_dn_by_oid()} use the information on known | ||
285 | OIDs to properly encode their input. Object Identifiers that are not | ||
286 | known are not encoded by these functions, and their input is stored directly | ||
287 | into the ASN.1 structure. In that case of unknown OIDs, you have | ||
288 | the responsibility of DER encoding your data. | ||
289 | |||
290 | Returns 1 on known OIDs and 0 otherwise. | ||
291 | @end deftypefun | ||
292 | |||
293 | @subheading gnutls_x509_crt_init | ||
294 | @anchor{gnutls_x509_crt_init} | ||
295 | @deftypefun {int} {gnutls_x509_crt_init} (gnutls_x509_crt_t * @var{cert}) | ||
296 | @var{cert}: The structure to be initialized | ||
297 | |||
298 | This function will initialize an X.509 certificate structure. | ||
299 | |||
300 | Returns 0 on success. | ||
301 | @end deftypefun | ||
302 | |||
303 | @subheading gnutls_x509_crt_deinit | ||
304 | @anchor{gnutls_x509_crt_deinit} | ||
305 | @deftypefun {void} {gnutls_x509_crt_deinit} (gnutls_x509_crt_t @var{cert}) | ||
306 | @var{cert}: The structure to be initialized | ||
307 | |||
308 | This function will deinitialize a CRL structure. | ||
309 | @end deftypefun | ||
310 | |||
311 | @subheading gnutls_x509_crt_import | ||
312 | @anchor{gnutls_x509_crt_import} | ||
313 | @deftypefun {int} {gnutls_x509_crt_import} (gnutls_x509_crt_t @var{cert}, const gnutls_datum_t * @var{data}, gnutls_x509_crt_fmt_t @var{format}) | ||
314 | @var{cert}: The structure to store the parsed certificate. | ||
315 | |||
316 | @var{data}: The DER or PEM encoded certificate. | ||
317 | |||
318 | @var{format}: One of DER or PEM | ||
319 | |||
320 | This function will convert the given DER or PEM encoded Certificate | ||
321 | to the native gnutls_x509_crt_t format. The output will be stored in @code{cert}. | ||
322 | |||
323 | If the Certificate is PEM encoded it should have a header of "X509 CERTIFICATE", or | ||
324 | "CERTIFICATE". | ||
325 | |||
326 | Returns 0 on success. | ||
327 | @end deftypefun | ||
328 | |||
329 | @subheading gnutls_x509_crt_get_issuer_dn | ||
330 | @anchor{gnutls_x509_crt_get_issuer_dn} | ||
331 | @deftypefun {int} {gnutls_x509_crt_get_issuer_dn} (gnutls_x509_crt_t @var{cert}, char * @var{buf}, size_t * @var{sizeof_buf}) | ||
332 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
333 | |||
334 | @var{buf}: a pointer to a structure to hold the name (may be null) | ||
335 | |||
336 | @var{sizeof_buf}: initially holds the size of @code{buf} | ||
337 | |||
338 | This function will copy the name of the Certificate issuer in the | ||
339 | provided buffer. The name will be in the form | ||
340 | "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253. The output string | ||
341 | will be ASCII or UTF-8 encoded, depending on the certificate data. | ||
342 | |||
343 | If @code{buf} is null then only the size will be filled. | ||
344 | |||
345 | Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not | ||
346 | long enough, and in that case the *sizeof_buf will be updated with | ||
347 | the required size. On success 0 is returned. | ||
348 | @end deftypefun | ||
349 | |||
350 | @subheading gnutls_x509_crt_get_issuer_dn_by_oid | ||
351 | @anchor{gnutls_x509_crt_get_issuer_dn_by_oid} | ||
352 | @deftypefun {int} {gnutls_x509_crt_get_issuer_dn_by_oid} (gnutls_x509_crt_t @var{cert}, const char * @var{oid}, int @var{indx}, unsigned int @var{raw_flag}, void * @var{buf}, size_t * @var{sizeof_buf}) | ||
353 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
354 | |||
355 | @var{oid}: holds an Object Identified in null terminated string | ||
356 | |||
357 | @var{indx}: In case multiple same OIDs exist in the RDN, this specifies which to send. Use zero to get the first one. | ||
358 | |||
359 | @var{raw_flag}: If non zero returns the raw DER data of the DN part. | ||
360 | |||
361 | @var{buf}: a pointer to a structure to hold the name (may be null) | ||
362 | |||
363 | @var{sizeof_buf}: initially holds the size of @code{buf} | ||
364 | |||
365 | This function will extract the part of the name of the Certificate | ||
366 | issuer specified by the given OID. The output, if the raw flag is not | ||
367 | used, will be encoded as described in RFC2253. Thus a string that is | ||
368 | ASCII or UTF-8 encoded, depending on the certificate data. | ||
369 | |||
370 | Some helper macros with popular OIDs can be found in gnutls/x509.h | ||
371 | If raw flag is zero, this function will only return known OIDs as | ||
372 | text. Other OIDs will be DER encoded, as described in RFC2253 -- | ||
373 | in hex format with a '\#' prefix. You can check about known OIDs | ||
374 | using @code{gnutls_x509_dn_oid_known()}. | ||
375 | |||
376 | If @code{buf} is null then only the size will be filled. | ||
377 | |||
378 | Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not | ||
379 | long enough, and in that case the *sizeof_buf will be updated with | ||
380 | the required size. On success 0 is returned. | ||
381 | @end deftypefun | ||
382 | |||
383 | @subheading gnutls_x509_crt_get_issuer_dn_oid | ||
384 | @anchor{gnutls_x509_crt_get_issuer_dn_oid} | ||
385 | @deftypefun {int} {gnutls_x509_crt_get_issuer_dn_oid} (gnutls_x509_crt_t @var{cert}, int @var{indx}, void * @var{oid}, size_t * @var{sizeof_oid}) | ||
386 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
387 | |||
388 | @var{indx}: This specifies which OID to return. Use zero to get the first one. | ||
389 | |||
390 | @var{oid}: a pointer to a buffer to hold the OID (may be null) | ||
391 | |||
392 | @var{sizeof_oid}: initially holds the size of @code{oid} | ||
393 | |||
394 | This function will extract the OIDs of the name of the Certificate | ||
395 | issuer specified by the given index. | ||
396 | |||
397 | If @code{oid} is null then only the size will be filled. | ||
398 | |||
399 | Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not | ||
400 | long enough, and in that case the *sizeof_oid will be updated with | ||
401 | the required size. On success 0 is returned. | ||
402 | @end deftypefun | ||
403 | |||
404 | @subheading gnutls_x509_crt_get_dn | ||
405 | @anchor{gnutls_x509_crt_get_dn} | ||
406 | @deftypefun {int} {gnutls_x509_crt_get_dn} (gnutls_x509_crt_t @var{cert}, char * @var{buf}, size_t * @var{sizeof_buf}) | ||
407 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
408 | |||
409 | @var{buf}: a pointer to a structure to hold the name (may be null) | ||
410 | |||
411 | @var{sizeof_buf}: initially holds the size of @code{buf} | ||
412 | |||
413 | This function will copy the name of the Certificate in the | ||
414 | provided buffer. The name will be in the form | ||
415 | "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253. The output string | ||
416 | will be ASCII or UTF-8 encoded, depending on the certificate data. | ||
417 | |||
418 | If @code{buf} is null then only the size will be filled. | ||
419 | |||
420 | Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not | ||
421 | long enough, and in that case the *sizeof_buf will be updated with | ||
422 | the required size. On success 0 is returned. | ||
423 | @end deftypefun | ||
424 | |||
425 | @subheading gnutls_x509_crt_get_dn_by_oid | ||
426 | @anchor{gnutls_x509_crt_get_dn_by_oid} | ||
427 | @deftypefun {int} {gnutls_x509_crt_get_dn_by_oid} (gnutls_x509_crt_t @var{cert}, const char * @var{oid}, int @var{indx}, unsigned int @var{raw_flag}, void * @var{buf}, size_t * @var{sizeof_buf}) | ||
428 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
429 | |||
430 | @var{oid}: holds an Object Identified in null terminated string | ||
431 | |||
432 | @var{indx}: In case multiple same OIDs exist in the RDN, this specifies which to send. Use zero to get the first one. | ||
433 | |||
434 | @var{raw_flag}: If non zero returns the raw DER data of the DN part. | ||
435 | |||
436 | @var{buf}: a pointer where the DN part will be copied (may be null). | ||
437 | |||
438 | @var{sizeof_buf}: initially holds the size of @code{buf} | ||
439 | |||
440 | This function will extract the part of the name of the Certificate | ||
441 | subject specified by the given OID. The output, if the raw flag is not | ||
442 | used, will be encoded as described in RFC2253. Thus a string that is | ||
443 | ASCII or UTF-8 encoded, depending on the certificate data. | ||
444 | |||
445 | Some helper macros with popular OIDs can be found in gnutls/x509.h | ||
446 | If raw flag is zero, this function will only return known OIDs as | ||
447 | text. Other OIDs will be DER encoded, as described in RFC2253 -- | ||
448 | in hex format with a '\#' prefix. You can check about known OIDs | ||
449 | using @code{gnutls_x509_dn_oid_known()}. | ||
450 | |||
451 | If @code{buf} is null then only the size will be filled. | ||
452 | |||
453 | Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not | ||
454 | long enough, and in that case the *sizeof_buf will be updated with | ||
455 | the required size. On success 0 is returned. | ||
456 | @end deftypefun | ||
457 | |||
458 | @subheading gnutls_x509_crt_get_dn_oid | ||
459 | @anchor{gnutls_x509_crt_get_dn_oid} | ||
460 | @deftypefun {int} {gnutls_x509_crt_get_dn_oid} (gnutls_x509_crt_t @var{cert}, int @var{indx}, void * @var{oid}, size_t * @var{sizeof_oid}) | ||
461 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
462 | |||
463 | @var{indx}: This specifies which OID to return. Use zero to get the first one. | ||
464 | |||
465 | @var{oid}: a pointer to a buffer to hold the OID (may be null) | ||
466 | |||
467 | @var{sizeof_oid}: initially holds the size of @code{oid} | ||
468 | |||
469 | This function will extract the OIDs of the name of the Certificate | ||
470 | subject specified by the given index. | ||
471 | |||
472 | If oid is null then only the size will be filled. | ||
473 | |||
474 | Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not | ||
475 | long enough, and in that case the *sizeof_oid will be updated with | ||
476 | the required size. On success 0 is returned. | ||
477 | @end deftypefun | ||
478 | |||
479 | @subheading gnutls_x509_crt_get_signature_algorithm | ||
480 | @anchor{gnutls_x509_crt_get_signature_algorithm} | ||
481 | @deftypefun {int} {gnutls_x509_crt_get_signature_algorithm} (gnutls_x509_crt_t @var{cert}) | ||
482 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
483 | |||
484 | This function will return a value of the gnutls_sign_algorithm_t enumeration that | ||
485 | is the signature algorithm. | ||
486 | |||
487 | Returns a negative value on error. | ||
488 | @end deftypefun | ||
489 | |||
490 | @subheading gnutls_x509_crt_get_signature | ||
491 | @anchor{gnutls_x509_crt_get_signature} | ||
492 | @deftypefun {int} {gnutls_x509_crt_get_signature} (gnutls_x509_crt_t @var{cert}, char * @var{sig}, size_t * @var{sizeof_sig}) | ||
493 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
494 | |||
495 | @var{sig}: a pointer where the signature part will be copied (may be null). | ||
496 | |||
497 | @var{sizeof_sig}: initially holds the size of @code{sig} | ||
498 | |||
499 | This function will extract the signature field of a certificate. | ||
500 | |||
501 | Returns 0 on success, and a negative value on error. | ||
502 | @end deftypefun | ||
503 | |||
504 | @subheading gnutls_x509_crt_get_version | ||
505 | @anchor{gnutls_x509_crt_get_version} | ||
506 | @deftypefun {int} {gnutls_x509_crt_get_version} (gnutls_x509_crt_t @var{cert}) | ||
507 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
508 | |||
509 | This function will return the version of the specified Certificate. | ||
510 | |||
511 | Returns a negative value on error. | ||
512 | @end deftypefun | ||
513 | |||
514 | @subheading gnutls_x509_crt_get_activation_time | ||
515 | @anchor{gnutls_x509_crt_get_activation_time} | ||
516 | @deftypefun {time_t} {gnutls_x509_crt_get_activation_time} (gnutls_x509_crt_t @var{cert}) | ||
517 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
518 | |||
519 | This function will return the time this Certificate was or will be activated. | ||
520 | |||
521 | Returns (time_t)-1 on error. | ||
522 | @end deftypefun | ||
523 | |||
524 | @subheading gnutls_x509_crt_get_expiration_time | ||
525 | @anchor{gnutls_x509_crt_get_expiration_time} | ||
526 | @deftypefun {time_t} {gnutls_x509_crt_get_expiration_time} (gnutls_x509_crt_t @var{cert}) | ||
527 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
528 | |||
529 | This function will return the time this Certificate was or will be expired. | ||
530 | |||
531 | Returns (time_t)-1 on error. | ||
532 | @end deftypefun | ||
533 | |||
534 | @subheading gnutls_x509_crt_get_serial | ||
535 | @anchor{gnutls_x509_crt_get_serial} | ||
536 | @deftypefun {int} {gnutls_x509_crt_get_serial} (gnutls_x509_crt_t @var{cert}, void * @var{result}, size_t * @var{result_size}) | ||
537 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
538 | |||
539 | @var{result}: The place where the serial number will be copied | ||
540 | |||
541 | @var{result_size}: Holds the size of the result field. | ||
542 | |||
543 | This function will return the X.509 certificate's serial number. | ||
544 | This is obtained by the X509 Certificate serialNumber | ||
545 | field. Serial is not always a 32 or 64bit number. Some CAs use | ||
546 | large serial numbers, thus it may be wise to handle it as something | ||
547 | opaque. | ||
548 | |||
549 | Returns 0 on success and a negative value in case of an error. | ||
550 | @end deftypefun | ||
551 | |||
552 | @subheading gnutls_x509_crt_get_subject_key_id | ||
553 | @anchor{gnutls_x509_crt_get_subject_key_id} | ||
554 | @deftypefun {int} {gnutls_x509_crt_get_subject_key_id} (gnutls_x509_crt_t @var{cert}, void * @var{ret}, size_t * @var{ret_size}, unsigned int * @var{critical}) | ||
555 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
556 | |||
557 | @var{ret}: The place where the identifier will be copied | ||
558 | |||
559 | @var{ret_size}: Holds the size of the result field. | ||
560 | |||
561 | @var{critical}: will be non zero if the extension is marked as critical (may be null) | ||
562 | |||
563 | This function will return the X.509v3 certificate's subject key identifier. | ||
564 | This is obtained by the X.509 Subject Key identifier extension | ||
565 | field (2.5.29.14). | ||
566 | |||
567 | Returns 0 on success and a negative value in case of an error. | ||
568 | @end deftypefun | ||
569 | |||
570 | @subheading gnutls_x509_crt_get_authority_key_id | ||
571 | @anchor{gnutls_x509_crt_get_authority_key_id} | ||
572 | @deftypefun {int} {gnutls_x509_crt_get_authority_key_id} (gnutls_x509_crt_t @var{cert}, void * @var{ret}, size_t * @var{ret_size}, unsigned int * @var{critical}) | ||
573 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
574 | |||
575 | @var{critical}: will be non zero if the extension is marked as critical (may be null) | ||
576 | |||
577 | This function will return the X.509v3 certificate authority's key identifier. | ||
578 | This is obtained by the X.509 Authority Key identifier extension | ||
579 | field (2.5.29.35). Note that this function only returns the keyIdentifier | ||
580 | field of the extension. | ||
581 | |||
582 | Returns 0 on success and a negative value in case of an error. | ||
583 | @end deftypefun | ||
584 | |||
585 | @subheading gnutls_x509_crt_get_pk_algorithm | ||
586 | @anchor{gnutls_x509_crt_get_pk_algorithm} | ||
587 | @deftypefun {int} {gnutls_x509_crt_get_pk_algorithm} (gnutls_x509_crt_t @var{cert}, unsigned int * @var{bits}) | ||
588 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
589 | |||
590 | @var{bits}: if bits is non null it will hold the size of the parameters' in bits | ||
591 | |||
592 | This function will return the public key algorithm of an X.509 | ||
593 | certificate. | ||
594 | |||
595 | If bits is non null, it should have enough size to hold the parameters | ||
596 | size in bits. For RSA the bits returned is the modulus. | ||
597 | For DSA the bits returned are of the public | ||
598 | exponent. | ||
599 | |||
600 | Returns a member of the gnutls_pk_algorithm_t enumeration on success, | ||
601 | or a negative value on error. | ||
602 | @end deftypefun | ||
603 | |||
604 | @subheading gnutls_x509_crt_get_subject_alt_name | ||
605 | @anchor{gnutls_x509_crt_get_subject_alt_name} | ||
606 | @deftypefun {int} {gnutls_x509_crt_get_subject_alt_name} (gnutls_x509_crt_t @var{cert}, unsigned int @var{seq}, void * @var{ret}, size_t * @var{ret_size}, unsigned int * @var{critical}) | ||
607 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
608 | |||
609 | @var{seq}: specifies the sequence number of the alt name (0 for the first one, 1 for the second etc.) | ||
610 | |||
611 | @var{ret}: is the place where the alternative name will be copied to | ||
612 | |||
613 | @var{ret_size}: holds the size of ret. | ||
614 | |||
615 | @var{critical}: will be non zero if the extension is marked as critical (may be null) | ||
616 | |||
617 | This function will return the alternative names, contained in the | ||
618 | given certificate. | ||
619 | |||
620 | This is specified in X509v3 Certificate Extensions. GNUTLS will | ||
621 | return the Alternative name (2.5.29.17), or a negative error code. | ||
622 | |||
623 | When the SAN type is otherName, it will extract the data in the | ||
624 | otherName's value field, and @code{GNUTLS_SAN_OTHERNAME} is returned. | ||
625 | You may use @code{gnutls_x509_crt_get_subject_alt_othername_oid()} to get | ||
626 | the corresponding OID and the "virtual" SAN types (e.g., | ||
627 | @code{GNUTLS_SAN_OTHERNAME_XMPP}). | ||
628 | |||
629 | If an otherName OID is known, the data will be decoded. Otherwise | ||
630 | the returned data will be DER encoded, and you will have to decode | ||
631 | it yourself. Currently, only the RFC 3920 id-on-xmppAddr SAN is | ||
632 | recognized. | ||
633 | |||
634 | Returns the alternative subject name type on success. The type is | ||
635 | one of the enumerated gnutls_x509_subject_alt_name_t. It will | ||
636 | return @code{GNUTLS_E_SHORT_MEMORY_BUFFER} if @code{ret_size} is not large | ||
637 | enough to hold the value. In that case @code{ret_size} will be updated | ||
638 | with the required size. If the certificate does not have an | ||
639 | Alternative name with the specified sequence number then | ||
640 | @code{GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE} is returned. | ||
641 | @end deftypefun | ||
642 | |||
643 | @subheading gnutls_x509_crt_get_subject_alt_name2 | ||
644 | @anchor{gnutls_x509_crt_get_subject_alt_name2} | ||
645 | @deftypefun {int} {gnutls_x509_crt_get_subject_alt_name2} (gnutls_x509_crt_t @var{cert}, unsigned int @var{seq}, void * @var{ret}, size_t * @var{ret_size}, unsigned int* @var{ret_type}, unsigned int * @var{critical}) | ||
646 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
647 | |||
648 | @var{seq}: specifies the sequence number of the alt name (0 for the first one, 1 for the second etc.) | ||
649 | |||
650 | @var{ret}: is the place where the alternative name will be copied to | ||
651 | |||
652 | @var{ret_size}: holds the size of ret. | ||
653 | |||
654 | @var{ret_type}: holds the type of the alternative name (one of gnutls_x509_subject_alt_name_t). | ||
655 | |||
656 | @var{critical}: will be non zero if the extension is marked as critical (may be null) | ||
657 | |||
658 | This function will return the alternative names, contained in the | ||
659 | given certificate. It is the same as @code{gnutls_x509_crt_get_subject_alt_name()} | ||
660 | except for the fact that it will return the type of the alternative | ||
661 | name in @code{ret_type} even if the function fails for some reason (i.e. | ||
662 | the buffer provided is not enough). | ||
663 | |||
664 | The return values are the same as with @code{gnutls_x509_crt_get_subject_alt_name()}. | ||
665 | @end deftypefun | ||
666 | |||
667 | @subheading gnutls_x509_crt_get_subject_alt_othername_oid | ||
668 | @anchor{gnutls_x509_crt_get_subject_alt_othername_oid} | ||
669 | @deftypefun {int} {gnutls_x509_crt_get_subject_alt_othername_oid} (gnutls_x509_crt_t @var{cert}, unsigned int @var{seq}, void * @var{ret}, size_t * @var{ret_size}) | ||
670 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
671 | |||
672 | @var{seq}: specifies the sequence number of the alt name (0 for the first one, 1 for the second etc.) | ||
673 | |||
674 | @var{ret}: is the place where the otherName OID will be copied to | ||
675 | |||
676 | @var{ret_size}: holds the size of ret. | ||
677 | |||
678 | This function will extract the type OID of an otherName Subject | ||
679 | Alternative Name, contained in the given certificate, and return | ||
680 | the type as an enumerated element. | ||
681 | |||
682 | This function is only useful if | ||
683 | @code{gnutls_x509_crt_get_subject_alt_name()} returned | ||
684 | @code{GNUTLS_SAN_OTHERNAME}. | ||
685 | |||
686 | Returns the alternative subject name type on success. The type is | ||
687 | one of the enumerated gnutls_x509_subject_alt_name_t. For | ||
688 | supported OIDs, it will return one of the virtual | ||
689 | (GNUTLS_SAN_OTHERNAME_*) types, e.g. @code{GNUTLS_SAN_OTHERNAME_XMPP}, | ||
690 | and @code{GNUTLS_SAN_OTHERNAME} for unknown OIDs. It will return | ||
691 | @code{GNUTLS_E_SHORT_MEMORY_BUFFER} if @code{ret_size} is not large enough to | ||
692 | hold the value. In that case @code{ret_size} will be updated with the | ||
693 | required size. If the certificate does not have an Alternative | ||
694 | name with the specified sequence number and with the otherName type | ||
695 | then @code{GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE} is returned. | ||
696 | @end deftypefun | ||
697 | |||
698 | @subheading gnutls_x509_crt_get_basic_constraints | ||
699 | @anchor{gnutls_x509_crt_get_basic_constraints} | ||
700 | @deftypefun {int} {gnutls_x509_crt_get_basic_constraints} (gnutls_x509_crt_t @var{cert}, unsigned int * @var{critical}, int * @var{ca}, int * @var{pathlen}) | ||
701 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
702 | |||
703 | @var{critical}: will be non zero if the extension is marked as critical | ||
704 | |||
705 | @var{ca}: pointer to output integer indicating CA status, may be NULL, | ||
706 | value is 1 if the certificate CA flag is set, 0 otherwise. | ||
707 | |||
708 | @var{pathlen}: pointer to output integer indicating path length (may be | ||
709 | NULL), non-negative values indicate a present pathLenConstraint | ||
710 | field and the actual value, -1 indicate that the field is absent. | ||
711 | |||
712 | This function will read the certificate's basic constraints, and | ||
713 | return the certificates CA status. It reads the basicConstraints | ||
714 | X.509 extension (2.5.29.19). | ||
715 | |||
716 | @strong{Return value:} If the certificate is a CA a positive value will be | ||
717 | returned, or zero if the certificate does not have CA flag set. A | ||
718 | negative value may be returned in case of errors. If the | ||
719 | certificate does not contain the basicConstraints extension | ||
720 | GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned. | ||
721 | @end deftypefun | ||
722 | |||
723 | @subheading gnutls_x509_crt_get_ca_status | ||
724 | @anchor{gnutls_x509_crt_get_ca_status} | ||
725 | @deftypefun {int} {gnutls_x509_crt_get_ca_status} (gnutls_x509_crt_t @var{cert}, unsigned int * @var{critical}) | ||
726 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
727 | |||
728 | @var{critical}: will be non zero if the extension is marked as critical | ||
729 | |||
730 | This function will return certificates CA status, by reading the | ||
731 | basicConstraints X.509 extension (2.5.29.19). If the certificate is | ||
732 | a CA a positive value will be returned, or zero if the certificate | ||
733 | does not have CA flag set. | ||
734 | |||
735 | Use @code{gnutls_x509_crt_get_basic_constraints()} if you want to read the | ||
736 | pathLenConstraint field too. | ||
737 | |||
738 | A negative value may be returned in case of parsing error. | ||
739 | If the certificate does not contain the basicConstraints extension | ||
740 | GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned. | ||
741 | @end deftypefun | ||
742 | |||
743 | @subheading gnutls_x509_crt_get_key_usage | ||
744 | @anchor{gnutls_x509_crt_get_key_usage} | ||
745 | @deftypefun {int} {gnutls_x509_crt_get_key_usage} (gnutls_x509_crt_t @var{cert}, unsigned int * @var{key_usage}, unsigned int * @var{critical}) | ||
746 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
747 | |||
748 | @var{key_usage}: where the key usage bits will be stored | ||
749 | |||
750 | @var{critical}: will be non zero if the extension is marked as critical | ||
751 | |||
752 | This function will return certificate's key usage, by reading the | ||
753 | keyUsage X.509 extension (2.5.29.15). The key usage value will ORed values of the: | ||
754 | GNUTLS_KEY_DIGITAL_SIGNATURE, GNUTLS_KEY_NON_REPUDIATION, | ||
755 | GNUTLS_KEY_KEY_ENCIPHERMENT, GNUTLS_KEY_DATA_ENCIPHERMENT, | ||
756 | GNUTLS_KEY_KEY_AGREEMENT, GNUTLS_KEY_KEY_CERT_SIGN, | ||
757 | GNUTLS_KEY_CRL_SIGN, GNUTLS_KEY_ENCIPHER_ONLY, | ||
758 | GNUTLS_KEY_DECIPHER_ONLY. | ||
759 | |||
760 | A negative value may be returned in case of parsing error. | ||
761 | If the certificate does not contain the keyUsage extension | ||
762 | GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned. | ||
763 | @end deftypefun | ||
764 | |||
765 | @subheading gnutls_x509_crt_get_proxy | ||
766 | @anchor{gnutls_x509_crt_get_proxy} | ||
767 | @deftypefun {int} {gnutls_x509_crt_get_proxy} (gnutls_x509_crt_t @var{cert}, unsigned int * @var{critical}, int * @var{pathlen}, char ** @var{policyLanguage}, char ** @var{policy}, size_t * @var{sizeof_policy}) | ||
768 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
769 | |||
770 | @var{critical}: will be non zero if the extension is marked as critical | ||
771 | |||
772 | @var{pathlen}: pointer to output integer indicating path length (may be | ||
773 | NULL), non-negative values indicate a present pCPathLenConstraint | ||
774 | field and the actual value, -1 indicate that the field is absent. | ||
775 | |||
776 | This function will read the certificate's basic constraints, and | ||
777 | return the certificates CA status. It reads the basicConstraints | ||
778 | X.509 extension (2.5.29.19). | ||
779 | |||
780 | @strong{Return value:} If the certificate is a CA a positive value will be | ||
781 | returned, or zero if the certificate does not have CA flag set. A | ||
782 | negative value may be returned in case of errors. If the | ||
783 | certificate does not contain the basicConstraints extension | ||
784 | GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned. | ||
785 | @end deftypefun | ||
786 | |||
787 | @subheading gnutls_x509_crt_get_extension_by_oid | ||
788 | @anchor{gnutls_x509_crt_get_extension_by_oid} | ||
789 | @deftypefun {int} {gnutls_x509_crt_get_extension_by_oid} (gnutls_x509_crt_t @var{cert}, const char * @var{oid}, int @var{indx}, void * @var{buf}, size_t * @var{sizeof_buf}, unsigned int * @var{critical}) | ||
790 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
791 | |||
792 | @var{oid}: holds an Object Identified in null terminated string | ||
793 | |||
794 | @var{indx}: In case multiple same OIDs exist in the extensions, this specifies which to send. Use zero to get the first one. | ||
795 | |||
796 | @var{buf}: a pointer to a structure to hold the name (may be null) | ||
797 | |||
798 | @var{sizeof_buf}: initially holds the size of @code{buf} | ||
799 | |||
800 | @var{critical}: will be non zero if the extension is marked as critical | ||
801 | |||
802 | This function will return the extension specified by the OID in the certificate. | ||
803 | The extensions will be returned as binary data DER encoded, in the provided | ||
804 | buffer. | ||
805 | |||
806 | A negative value may be returned in case of parsing error. | ||
807 | If the certificate does not contain the specified extension | ||
808 | GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned. | ||
809 | @end deftypefun | ||
810 | |||
811 | @subheading gnutls_x509_crt_get_extension_oid | ||
812 | @anchor{gnutls_x509_crt_get_extension_oid} | ||
813 | @deftypefun {int} {gnutls_x509_crt_get_extension_oid} (gnutls_x509_crt_t @var{cert}, int @var{indx}, void * @var{oid}, size_t * @var{sizeof_oid}) | ||
814 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
815 | |||
816 | @var{indx}: Specifies which extension OID to send. Use zero to get the first one. | ||
817 | |||
818 | @var{oid}: a pointer to a structure to hold the OID (may be null) | ||
819 | |||
820 | @var{sizeof_oid}: initially holds the size of @code{oid} | ||
821 | |||
822 | This function will return the requested extension OID in the certificate. | ||
823 | The extension OID will be stored as a string in the provided buffer. | ||
824 | |||
825 | A negative value may be returned in case of parsing error. | ||
826 | If your have reached the last extension available | ||
827 | GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned. | ||
828 | @end deftypefun | ||
829 | |||
830 | @subheading gnutls_x509_crt_get_extension_info | ||
831 | @anchor{gnutls_x509_crt_get_extension_info} | ||
832 | @deftypefun {int} {gnutls_x509_crt_get_extension_info} (gnutls_x509_crt_t @var{cert}, int @var{indx}, void * @var{oid}, size_t * @var{sizeof_oid}, int * @var{critical}) | ||
833 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
834 | |||
835 | @var{indx}: Specifies which extension OID to send. Use zero to get the first one. | ||
836 | |||
837 | @var{oid}: a pointer to a structure to hold the OID | ||
838 | |||
839 | @var{sizeof_oid}: initially holds the size of @code{oid} | ||
840 | |||
841 | @var{critical}: output variable with critical flag, may be NULL. | ||
842 | |||
843 | This function will return the requested extension OID in the | ||
844 | certificate, and the critical flag for it. The extension OID will | ||
845 | be stored as a string in the provided buffer. Use | ||
846 | @code{gnutls_x509_crt_get_extension_data()} to extract the data. | ||
847 | |||
848 | Return 0 on success. A negative value may be returned in case of | ||
849 | parsing error. If you have reached the last extension available | ||
850 | GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned. | ||
851 | @end deftypefun | ||
852 | |||
853 | @subheading gnutls_x509_crt_get_extension_data | ||
854 | @anchor{gnutls_x509_crt_get_extension_data} | ||
855 | @deftypefun {int} {gnutls_x509_crt_get_extension_data} (gnutls_x509_crt_t @var{cert}, int @var{indx}, void * @var{data}, size_t * @var{sizeof_data}) | ||
856 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
857 | |||
858 | @var{indx}: Specifies which extension OID to send. Use zero to get the first one. | ||
859 | |||
860 | @var{data}: a pointer to a structure to hold the data (may be null) | ||
861 | |||
862 | @var{sizeof_data}: initially holds the size of @code{oid} | ||
863 | |||
864 | This function will return the requested extension data in the | ||
865 | certificate. The extension data will be stored as a string in the | ||
866 | provided buffer. | ||
867 | |||
868 | Use @code{gnutls_x509_crt_get_extension_info()} to extract the OID and | ||
869 | critical flag. Use @code{gnutls_x509_crt_get_extension_by_oid()} instead, | ||
870 | if you want to get data indexed by the extension OID rather than | ||
871 | sequence. | ||
872 | |||
873 | Return 0 on success. A negative value may be returned in case of | ||
874 | parsing error. If you have reached the last extension available | ||
875 | GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned. | ||
876 | @end deftypefun | ||
877 | |||
878 | @subheading gnutls_x509_crt_get_raw_issuer_dn | ||
879 | @anchor{gnutls_x509_crt_get_raw_issuer_dn} | ||
880 | @deftypefun {int} {gnutls_x509_crt_get_raw_issuer_dn} (gnutls_x509_crt_t @var{cert}, gnutls_datum_t * @var{start}) | ||
881 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
882 | |||
883 | @var{start}: will hold the starting point of the DN | ||
884 | |||
885 | This function will return a pointer to the DER encoded DN structure | ||
886 | and the length. | ||
887 | |||
888 | Returns 0 on success or a negative value on error. | ||
889 | @end deftypefun | ||
890 | |||
891 | @subheading gnutls_x509_crt_get_raw_dn | ||
892 | @anchor{gnutls_x509_crt_get_raw_dn} | ||
893 | @deftypefun {int} {gnutls_x509_crt_get_raw_dn} (gnutls_x509_crt_t @var{cert}, gnutls_datum_t * @var{start}) | ||
894 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
895 | |||
896 | @var{start}: will hold the starting point of the DN | ||
897 | |||
898 | This function will return a pointer to the DER encoded DN structure and | ||
899 | the length. | ||
900 | |||
901 | Returns 0 on success, or a negative value on error. | ||
902 | @end deftypefun | ||
903 | |||
904 | @subheading gnutls_x509_crt_get_subject | ||
905 | @anchor{gnutls_x509_crt_get_subject} | ||
906 | @deftypefun {int} {gnutls_x509_crt_get_subject} (gnutls_x509_crt_t @var{cert}, gnutls_x509_dn_t * @var{dn}) | ||
907 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
908 | |||
909 | @var{dn}: output variable with pointer to opaque DN. | ||
910 | |||
911 | Return the Certificate's Subject DN as an opaque data type. You | ||
912 | may use @code{gnutls_x509_dn_get_rdn_ava()} to decode the DN. | ||
913 | |||
914 | @strong{Returns:} Returns 0 on success, or an error code. | ||
915 | @end deftypefun | ||
916 | |||
917 | @subheading gnutls_x509_crt_get_issuer | ||
918 | @anchor{gnutls_x509_crt_get_issuer} | ||
919 | @deftypefun {int} {gnutls_x509_crt_get_issuer} (gnutls_x509_crt_t @var{cert}, gnutls_x509_dn_t * @var{dn}) | ||
920 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
921 | |||
922 | @var{dn}: output variable with pointer to opaque DN | ||
923 | |||
924 | Return the Certificate's Issuer DN as an opaque data type. You may | ||
925 | use @code{gnutls_x509_dn_get_rdn_ava()} to decode the DN. | ||
926 | |||
927 | Note that @code{dn} points into the @code{cert} object, and thus you may not | ||
928 | deallocate @code{cert} and continue to access @code{dn}. | ||
929 | |||
930 | @strong{Returns:} Returns 0 on success, or an error code. | ||
931 | @end deftypefun | ||
932 | |||
933 | @subheading gnutls_x509_dn_get_rdn_ava | ||
934 | @anchor{gnutls_x509_dn_get_rdn_ava} | ||
935 | @deftypefun {int} {gnutls_x509_dn_get_rdn_ava} (gnutls_x509_dn_t @var{dn}, int @var{irdn}, int @var{iava}, gnutls_x509_ava_st * @var{ava}) | ||
936 | @var{dn}: input variable with opaque DN pointer | ||
937 | |||
938 | @var{irdn}: index of RDN | ||
939 | |||
940 | @var{iava}: index of AVA. | ||
941 | |||
942 | @var{ava}: Pointer to structure which will hold output information. | ||
943 | |||
944 | Get pointers to data within the DN. | ||
945 | |||
946 | Note that @code{ava} will contain pointers into the @code{dn} structure, so you | ||
947 | should not modify any data or deallocate it. Note also that the DN | ||
948 | in turn points into the original certificate structure, and thus | ||
949 | you may not deallocate the certificate and continue to access @code{dn}. | ||
950 | |||
951 | @strong{Returns:} Returns 0 on success, or an error code. | ||
952 | @end deftypefun | ||
953 | |||
954 | @subheading gnutls_x509_crt_get_fingerprint | ||
955 | @anchor{gnutls_x509_crt_get_fingerprint} | ||
956 | @deftypefun {int} {gnutls_x509_crt_get_fingerprint} (gnutls_x509_crt_t @var{cert}, gnutls_digest_algorithm_t @var{algo}, void * @var{buf}, size_t * @var{sizeof_buf}) | ||
957 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
958 | |||
959 | @var{algo}: is a digest algorithm | ||
960 | |||
961 | @var{buf}: a pointer to a structure to hold the fingerprint (may be null) | ||
962 | |||
963 | @var{sizeof_buf}: initially holds the size of @code{buf} | ||
964 | |||
965 | This function will calculate and copy the certificate's fingerprint | ||
966 | in the provided buffer. | ||
967 | |||
968 | If the buffer is null then only the size will be filled. | ||
969 | |||
970 | @strong{Returns:} @code{GNUTLS_E_SHORT_MEMORY_BUFFER} if the provided buffer is | ||
971 | not long enough, and in that case the *sizeof_buf will be updated | ||
972 | with the required size. On success 0 is returned. | ||
973 | @end deftypefun | ||
974 | |||
975 | @subheading gnutls_x509_crt_export | ||
976 | @anchor{gnutls_x509_crt_export} | ||
977 | @deftypefun {int} {gnutls_x509_crt_export} (gnutls_x509_crt_t @var{cert}, gnutls_x509_crt_fmt_t @var{format}, void * @var{output_data}, size_t * @var{output_data_size}) | ||
978 | @var{cert}: Holds the certificate | ||
979 | |||
980 | @var{format}: the format of output params. One of PEM or DER. | ||
981 | |||
982 | @var{output_data}: will contain a certificate PEM or DER encoded | ||
983 | |||
984 | @var{output_data_size}: holds the size of output_data (and will be | ||
985 | replaced by the actual size of parameters) | ||
986 | |||
987 | This function will export the certificate to DER or PEM format. | ||
988 | |||
989 | If the buffer provided is not long enough to hold the output, then | ||
990 | *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will | ||
991 | be returned. | ||
992 | |||
993 | If the structure is PEM encoded, it will have a header | ||
994 | of "BEGIN CERTIFICATE". | ||
995 | |||
996 | @strong{Return value:} In case of failure a negative value will be | ||
997 | returned, and 0 on success. | ||
998 | @end deftypefun | ||
999 | |||
1000 | @subheading gnutls_x509_crt_get_key_id | ||
1001 | @anchor{gnutls_x509_crt_get_key_id} | ||
1002 | @deftypefun {int} {gnutls_x509_crt_get_key_id} (gnutls_x509_crt_t @var{crt}, unsigned int @var{flags}, unsigned char * @var{output_data}, size_t * @var{output_data_size}) | ||
1003 | @var{crt}: Holds the certificate | ||
1004 | |||
1005 | @var{flags}: should be 0 for now | ||
1006 | |||
1007 | @var{output_data}: will contain the key ID | ||
1008 | |||
1009 | @var{output_data_size}: holds the size of output_data (and will be | ||
1010 | replaced by the actual size of parameters) | ||
1011 | |||
1012 | This function will return a unique ID the depends on the public | ||
1013 | key parameters. This ID can be used in checking whether a | ||
1014 | certificate corresponds to the given private key. | ||
1015 | |||
1016 | If the buffer provided is not long enough to hold the output, then | ||
1017 | *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will | ||
1018 | be returned. The output will normally be a SHA-1 hash output, | ||
1019 | which is 20 bytes. | ||
1020 | |||
1021 | @strong{Return value:} In case of failure a negative value will be | ||
1022 | returned, and 0 on success. | ||
1023 | @end deftypefun | ||
1024 | |||
1025 | @subheading gnutls_x509_crt_check_revocation | ||
1026 | @anchor{gnutls_x509_crt_check_revocation} | ||
1027 | @deftypefun {int} {gnutls_x509_crt_check_revocation} (gnutls_x509_crt_t @var{cert}, const gnutls_x509_crl_t * @var{crl_list}, int @var{crl_list_length}) | ||
1028 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
1029 | |||
1030 | @var{crl_list}: should contain a list of gnutls_x509_crl_t structures | ||
1031 | |||
1032 | @var{crl_list_length}: the length of the crl_list | ||
1033 | |||
1034 | This function will return check if the given certificate is | ||
1035 | revoked. It is assumed that the CRLs have been verified before. | ||
1036 | |||
1037 | @strong{Returns:} 0 if the certificate is NOT revoked, and 1 if it is. A | ||
1038 | negative value is returned on error. | ||
1039 | @end deftypefun | ||
1040 | |||
1041 | @subheading gnutls_x509_crt_verify_data | ||
1042 | @anchor{gnutls_x509_crt_verify_data} | ||
1043 | @deftypefun {int} {gnutls_x509_crt_verify_data} (gnutls_x509_crt_t @var{crt}, unsigned int @var{flags}, const gnutls_datum_t * @var{data}, const gnutls_datum_t * @var{signature}) | ||
1044 | @var{crt}: Holds the certificate | ||
1045 | |||
1046 | @var{flags}: should be 0 for now | ||
1047 | |||
1048 | @var{data}: holds the data to be signed | ||
1049 | |||
1050 | @var{signature}: contains the signature | ||
1051 | |||
1052 | This function will verify the given signed data, using the | ||
1053 | parameters from the certificate. | ||
1054 | |||
1055 | @strong{Returns:} In case of a verification failure 0 is returned, and 1 on | ||
1056 | success. | ||
1057 | @end deftypefun | ||
1058 | |||
1059 | @subheading gnutls_x509_crt_get_crl_dist_points | ||
1060 | @anchor{gnutls_x509_crt_get_crl_dist_points} | ||
1061 | @deftypefun {int} {gnutls_x509_crt_get_crl_dist_points} (gnutls_x509_crt_t @var{cert}, unsigned int @var{seq}, void * @var{ret}, size_t * @var{ret_size}, unsigned int * @var{reason_flags}, unsigned int * @var{critical}) | ||
1062 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
1063 | |||
1064 | @var{seq}: specifies the sequence number of the distribution point (0 for the first one, 1 for the second etc.) | ||
1065 | |||
1066 | @var{ret}: is the place where the distribution point will be copied to | ||
1067 | |||
1068 | @var{ret_size}: holds the size of ret. | ||
1069 | |||
1070 | @var{reason_flags}: Revocation reasons flags. | ||
1071 | |||
1072 | @var{critical}: will be non zero if the extension is marked as critical (may be null) | ||
1073 | |||
1074 | This function will return the CRL distribution points (2.5.29.31), | ||
1075 | contained in the given certificate. | ||
1076 | |||
1077 | @code{reason_flags} should be an ORed sequence of | ||
1078 | GNUTLS_CRL_REASON_UNUSED, GNUTLS_CRL_REASON_KEY_COMPROMISE, | ||
1079 | GNUTLS_CRL_REASON_CA_COMPROMISE, | ||
1080 | GNUTLS_CRL_REASON_AFFILIATION_CHANGED, | ||
1081 | GNUTLS_CRL_REASON_SUPERSEEDED, | ||
1082 | GNUTLS_CRL_REASON_CESSATION_OF_OPERATION, | ||
1083 | GNUTLS_CRL_REASON_CERTIFICATE_HOLD, | ||
1084 | GNUTLS_CRL_REASON_PRIVILEGE_WITHDRAWN, | ||
1085 | GNUTLS_CRL_REASON_AA_COMPROMISE, or zero for all possible reasons. | ||
1086 | |||
1087 | This is specified in X509v3 Certificate Extensions. GNUTLS will | ||
1088 | return the distribution point type, or a negative error code on | ||
1089 | error. | ||
1090 | |||
1091 | Returns @code{GNUTLS_E_SHORT_MEMORY_BUFFER} and updates &@code{ret_size} if | ||
1092 | &@code{ret_size} is not enough to hold the distribution point, or the | ||
1093 | type of the distribution point if everything was ok. The type is | ||
1094 | one of the enumerated @code{gnutls_x509_subject_alt_name_t}. If the | ||
1095 | certificate does not have an Alternative name with the specified | ||
1096 | sequence number then @code{GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE} is | ||
1097 | returned. | ||
1098 | @end deftypefun | ||
1099 | |||
1100 | @subheading gnutls_x509_crt_get_key_purpose_oid | ||
1101 | @anchor{gnutls_x509_crt_get_key_purpose_oid} | ||
1102 | @deftypefun {int} {gnutls_x509_crt_get_key_purpose_oid} (gnutls_x509_crt_t @var{cert}, int @var{indx}, void * @var{oid}, size_t * @var{sizeof_oid}, unsigned int * @var{critical}) | ||
1103 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
1104 | |||
1105 | @var{indx}: This specifies which OID to return. Use zero to get the first one. | ||
1106 | |||
1107 | @var{oid}: a pointer to a buffer to hold the OID (may be null) | ||
1108 | |||
1109 | @var{sizeof_oid}: initially holds the size of @code{oid} | ||
1110 | |||
1111 | This function will extract the key purpose OIDs of the Certificate | ||
1112 | specified by the given index. These are stored in the Extended Key | ||
1113 | Usage extension (2.5.29.37) See the GNUTLS_KP_* definitions for | ||
1114 | human readable names. | ||
1115 | |||
1116 | If @code{oid} is null then only the size will be filled. | ||
1117 | |||
1118 | @strong{Returns:} @code{GNUTLS_E_SHORT_MEMORY_BUFFER} if the provided buffer is | ||
1119 | not long enough, and in that case the *sizeof_oid will be updated | ||
1120 | with the required size. On success 0 is returned. | ||
1121 | @end deftypefun | ||
1122 | |||
1123 | @subheading gnutls_x509_crt_get_pk_rsa_raw | ||
1124 | @anchor{gnutls_x509_crt_get_pk_rsa_raw} | ||
1125 | @deftypefun {int} {gnutls_x509_crt_get_pk_rsa_raw} (gnutls_x509_crt_t @var{crt}, gnutls_datum_t * @var{m}, gnutls_datum_t * @var{e}) | ||
1126 | @var{crt}: Holds the certificate | ||
1127 | |||
1128 | @var{m}: will hold the modulus | ||
1129 | |||
1130 | @var{e}: will hold the public exponent | ||
1131 | |||
1132 | This function will export the RSA public key's parameters found in | ||
1133 | the given structure. The new parameters will be allocated using | ||
1134 | @code{gnutls_malloc()} and will be stored in the appropriate datum. | ||
1135 | |||
1136 | @strong{Returns:} @code{GNUTLS_E_SUCCESS} on success, otherwise an error. | ||
1137 | @end deftypefun | ||
1138 | |||
1139 | @subheading gnutls_x509_crt_get_pk_dsa_raw | ||
1140 | @anchor{gnutls_x509_crt_get_pk_dsa_raw} | ||
1141 | @deftypefun {int} {gnutls_x509_crt_get_pk_dsa_raw} (gnutls_x509_crt_t @var{crt}, gnutls_datum_t * @var{p}, gnutls_datum_t * @var{q}, gnutls_datum_t * @var{g}, gnutls_datum_t * @var{y}) | ||
1142 | @var{crt}: Holds the certificate | ||
1143 | |||
1144 | @var{p}: will hold the p | ||
1145 | |||
1146 | @var{q}: will hold the q | ||
1147 | |||
1148 | @var{g}: will hold the g | ||
1149 | |||
1150 | @var{y}: will hold the y | ||
1151 | |||
1152 | This function will export the DSA public key's parameters found in | ||
1153 | the given certificate. The new parameters will be allocated using | ||
1154 | @code{gnutls_malloc()} and will be stored in the appropriate datum. | ||
1155 | |||
1156 | @strong{Returns:} @code{GNUTLS_E_SUCCESS} on success, otherwise an error. | ||
1157 | @end deftypefun | ||
1158 | |||
1159 | @subheading gnutls_x509_crt_list_import | ||
1160 | @anchor{gnutls_x509_crt_list_import} | ||
1161 | @deftypefun {int} {gnutls_x509_crt_list_import} (gnutls_x509_crt_t * @var{certs}, unsigned int * @var{cert_max}, const gnutls_datum_t * @var{data}, gnutls_x509_crt_fmt_t @var{format}, unsigned int @var{flags}) | ||
1162 | @var{certs}: The structures to store the parsed certificate. Must not be initialized. | ||
1163 | |||
1164 | @var{cert_max}: Initially must hold the maximum number of certs. It will be updated with the number of certs available. | ||
1165 | |||
1166 | @var{data}: The PEM encoded certificate. | ||
1167 | |||
1168 | @var{format}: One of DER or PEM. | ||
1169 | |||
1170 | @var{flags}: must be zero or an OR'd sequence of gnutls_certificate_import_flags. | ||
1171 | |||
1172 | This function will convert the given PEM encoded certificate list | ||
1173 | to the native gnutls_x509_crt_t format. The output will be stored | ||
1174 | in @code{certs}. They will be automatically initialized. | ||
1175 | |||
1176 | If the Certificate is PEM encoded it should have a header of "X509 | ||
1177 | CERTIFICATE", or "CERTIFICATE". | ||
1178 | |||
1179 | @strong{Returns:} the number of certificates read or a negative error value. | ||
1180 | @end deftypefun | ||
1181 | |||
1182 | @subheading gnutls_x509_crt_check_hostname | ||
1183 | @anchor{gnutls_x509_crt_check_hostname} | ||
1184 | @deftypefun {int} {gnutls_x509_crt_check_hostname} (gnutls_x509_crt_t @var{cert}, const char * @var{hostname}) | ||
1185 | @var{cert}: should contain an gnutls_x509_crt_t structure | ||
1186 | |||
1187 | @var{hostname}: A null terminated string that contains a DNS name | ||
1188 | |||
1189 | This function will check if the given certificate's subject | ||
1190 | matches the given hostname. This is a basic implementation of the | ||
1191 | matching described in RFC2818 (HTTPS), which takes into account | ||
1192 | wildcards, and the DNSName/IPAddress subject alternative name PKIX | ||
1193 | extension. | ||
1194 | |||
1195 | Returns non zero for a successful match, and zero on failure. | ||
1196 | @end deftypefun | ||
1197 | |||
1198 | @subheading gnutls_x509_crt_check_issuer | ||
1199 | @anchor{gnutls_x509_crt_check_issuer} | ||
1200 | @deftypefun {int} {gnutls_x509_crt_check_issuer} (gnutls_x509_crt_t @var{cert}, gnutls_x509_crt_t @var{issuer}) | ||
1201 | @var{cert}: is the certificate to be checked | ||
1202 | |||
1203 | @var{issuer}: is the certificate of a possible issuer | ||
1204 | |||
1205 | This function will check if the given certificate was issued by the | ||
1206 | given issuer. It will return true (1) if the given certificate is issued | ||
1207 | by the given issuer, and false (0) if not. | ||
1208 | |||
1209 | A negative value is returned in case of an error. | ||
1210 | @end deftypefun | ||
1211 | |||
1212 | @subheading gnutls_x509_crt_list_verify | ||
1213 | @anchor{gnutls_x509_crt_list_verify} | ||
1214 | @deftypefun {int} {gnutls_x509_crt_list_verify} (const gnutls_x509_crt_t * @var{cert_list}, int @var{cert_list_length}, const gnutls_x509_crt_t * @var{CA_list}, int @var{CA_list_length}, const gnutls_x509_crl_t * @var{CRL_list}, int @var{CRL_list_length}, unsigned int @var{flags}, unsigned int * @var{verify}) | ||
1215 | @var{cert_list}: is the certificate list to be verified | ||
1216 | |||
1217 | @var{cert_list_length}: holds the number of certificate in cert_list | ||
1218 | |||
1219 | @var{CA_list}: is the CA list which will be used in verification | ||
1220 | |||
1221 | @var{CA_list_length}: holds the number of CA certificate in CA_list | ||
1222 | |||
1223 | @var{CRL_list}: holds a list of CRLs. | ||
1224 | |||
1225 | @var{CRL_list_length}: the length of CRL list. | ||
1226 | |||
1227 | @var{flags}: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations. | ||
1228 | |||
1229 | @var{verify}: will hold the certificate verification output. | ||
1230 | |||
1231 | This function will try to verify the given certificate list and return its status. | ||
1232 | Note that expiration and activation dates are not checked | ||
1233 | by this function, you should check them using the appropriate functions. | ||
1234 | |||
1235 | If no flags are specified (0), this function will use the | ||
1236 | basicConstraints (2.5.29.19) PKIX extension. This means that only a certificate | ||
1237 | authority is allowed to sign a certificate. | ||
1238 | |||
1239 | You must also check the peer's name in order to check if the verified | ||
1240 | certificate belongs to the actual peer. | ||
1241 | |||
1242 | The certificate verification output will be put in @code{verify} and will be | ||
1243 | one or more of the gnutls_certificate_status_t enumerated elements bitwise or'd. | ||
1244 | For a more detailed verification status use @code{gnutls_x509_crt_verify()} per list | ||
1245 | element. | ||
1246 | |||
1247 | @strong{GNUTLS_CERT_INVALID:} the certificate chain is not valid. | ||
1248 | |||
1249 | @strong{GNUTLS_CERT_REVOKED:} a certificate in the chain has been revoked. | ||
1250 | |||
1251 | Returns 0 on success and a negative value in case of an error. | ||
1252 | @end deftypefun | ||
1253 | |||
1254 | @subheading gnutls_x509_crt_verify | ||
1255 | @anchor{gnutls_x509_crt_verify} | ||
1256 | @deftypefun {int} {gnutls_x509_crt_verify} (gnutls_x509_crt_t @var{cert}, const gnutls_x509_crt_t * @var{CA_list}, int @var{CA_list_length}, unsigned int @var{flags}, unsigned int * @var{verify}) | ||
1257 | @var{cert}: is the certificate to be verified | ||
1258 | |||
1259 | @var{CA_list}: is one certificate that is considered to be trusted one | ||
1260 | |||
1261 | @var{CA_list_length}: holds the number of CA certificate in CA_list | ||
1262 | |||
1263 | @var{flags}: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations. | ||
1264 | |||
1265 | @var{verify}: will hold the certificate verification output. | ||
1266 | |||
1267 | This function will try to verify the given certificate and return its status. | ||
1268 | The verification output in this functions cannot be GNUTLS_CERT_NOT_VALID. | ||
1269 | |||
1270 | Returns 0 on success and a negative value in case of an error. | ||
1271 | @end deftypefun | ||
1272 | |||
1273 | @subheading gnutls_x509_crl_check_issuer | ||
1274 | @anchor{gnutls_x509_crl_check_issuer} | ||
1275 | @deftypefun {int} {gnutls_x509_crl_check_issuer} (gnutls_x509_crl_t @var{cert}, gnutls_x509_crt_t @var{issuer}) | ||
1276 | @var{issuer}: is the certificate of a possible issuer | ||
1277 | |||
1278 | This function will check if the given CRL was issued by the | ||
1279 | given issuer certificate. It will return true (1) if the given CRL was issued | ||
1280 | by the given issuer, and false (0) if not. | ||
1281 | |||
1282 | A negative value is returned in case of an error. | ||
1283 | @end deftypefun | ||
1284 | |||
1285 | @subheading gnutls_x509_crl_verify | ||
1286 | @anchor{gnutls_x509_crl_verify} | ||
1287 | @deftypefun {int} {gnutls_x509_crl_verify} (gnutls_x509_crl_t @var{crl}, const gnutls_x509_crt_t * @var{CA_list}, int @var{CA_list_length}, unsigned int @var{flags}, unsigned int * @var{verify}) | ||
1288 | @var{crl}: is the crl to be verified | ||
1289 | |||
1290 | @var{CA_list}: is a certificate list that is considered to be trusted one | ||
1291 | |||
1292 | @var{CA_list_length}: holds the number of CA certificates in CA_list | ||
1293 | |||
1294 | @var{flags}: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations. | ||
1295 | |||
1296 | @var{verify}: will hold the crl verification output. | ||
1297 | |||
1298 | This function will try to verify the given crl and return its status. | ||
1299 | See @code{gnutls_x509_crt_list_verify()} for a detailed description of | ||
1300 | return values. | ||
1301 | |||
1302 | Returns 0 on success and a negative value in case of an error. | ||
1303 | @end deftypefun | ||
1304 | |||
1305 | @subheading gnutls_x509_privkey_init | ||
1306 | @anchor{gnutls_x509_privkey_init} | ||
1307 | @deftypefun {int} {gnutls_x509_privkey_init} (gnutls_x509_privkey_t * @var{key}) | ||
1308 | @var{key}: The structure to be initialized | ||
1309 | |||
1310 | This function will initialize an private key structure. | ||
1311 | |||
1312 | Returns 0 on success. | ||
1313 | @end deftypefun | ||
1314 | |||
1315 | @subheading gnutls_x509_privkey_deinit | ||
1316 | @anchor{gnutls_x509_privkey_deinit} | ||
1317 | @deftypefun {void} {gnutls_x509_privkey_deinit} (gnutls_x509_privkey_t @var{key}) | ||
1318 | @var{key}: The structure to be initialized | ||
1319 | |||
1320 | This function will deinitialize a private key structure. | ||
1321 | @end deftypefun | ||
1322 | |||
1323 | @subheading gnutls_x509_privkey_cpy | ||
1324 | @anchor{gnutls_x509_privkey_cpy} | ||
1325 | @deftypefun {int} {gnutls_x509_privkey_cpy} (gnutls_x509_privkey_t @var{dst}, gnutls_x509_privkey_t @var{src}) | ||
1326 | @var{dst}: The destination key, which should be initialized. | ||
1327 | |||
1328 | @var{src}: The source key | ||
1329 | |||
1330 | This function will copy a private key from source to destination key. | ||
1331 | @end deftypefun | ||
1332 | |||
1333 | @subheading gnutls_x509_privkey_import | ||
1334 | @anchor{gnutls_x509_privkey_import} | ||
1335 | @deftypefun {int} {gnutls_x509_privkey_import} (gnutls_x509_privkey_t @var{key}, const gnutls_datum_t * @var{data}, gnutls_x509_crt_fmt_t @var{format}) | ||
1336 | @var{key}: The structure to store the parsed key | ||
1337 | |||
1338 | @var{data}: The DER or PEM encoded certificate. | ||
1339 | |||
1340 | @var{format}: One of DER or PEM | ||
1341 | |||
1342 | This function will convert the given DER or PEM encoded key | ||
1343 | to the native gnutls_x509_privkey_t format. The output will be stored in @code{key} . | ||
1344 | |||
1345 | If the key is PEM encoded it should have a header of "RSA PRIVATE KEY", or | ||
1346 | "DSA PRIVATE KEY". | ||
1347 | |||
1348 | Returns 0 on success. | ||
1349 | @end deftypefun | ||
1350 | |||
1351 | @subheading gnutls_x509_privkey_import_rsa_raw | ||
1352 | @anchor{gnutls_x509_privkey_import_rsa_raw} | ||
1353 | @deftypefun {int} {gnutls_x509_privkey_import_rsa_raw} (gnutls_x509_privkey_t @var{key}, const gnutls_datum_t * @var{m}, const gnutls_datum_t * @var{e}, const gnutls_datum_t * @var{d}, const gnutls_datum_t * @var{p}, const gnutls_datum_t * @var{q}, const gnutls_datum_t * @var{u}) | ||
1354 | @var{key}: The structure to store the parsed key | ||
1355 | |||
1356 | @var{m}: holds the modulus | ||
1357 | |||
1358 | @var{e}: holds the public exponent | ||
1359 | |||
1360 | @var{d}: holds the private exponent | ||
1361 | |||
1362 | @var{p}: holds the first prime (p) | ||
1363 | |||
1364 | @var{q}: holds the second prime (q) | ||
1365 | |||
1366 | @var{u}: holds the coefficient | ||
1367 | |||
1368 | This function will convert the given RSA raw parameters | ||
1369 | to the native gnutls_x509_privkey_t format. The output will be stored in @code{key}. | ||
1370 | @end deftypefun | ||
1371 | |||
1372 | @subheading gnutls_x509_privkey_import_dsa_raw | ||
1373 | @anchor{gnutls_x509_privkey_import_dsa_raw} | ||
1374 | @deftypefun {int} {gnutls_x509_privkey_import_dsa_raw} (gnutls_x509_privkey_t @var{key}, const gnutls_datum_t * @var{p}, const gnutls_datum_t * @var{q}, const gnutls_datum_t * @var{g}, const gnutls_datum_t * @var{y}, const gnutls_datum_t * @var{x}) | ||
1375 | @var{key}: The structure to store the parsed key | ||
1376 | |||
1377 | @var{p}: holds the p | ||
1378 | |||
1379 | @var{q}: holds the q | ||
1380 | |||
1381 | @var{g}: holds the g | ||
1382 | |||
1383 | @var{y}: holds the y | ||
1384 | |||
1385 | @var{x}: holds the x | ||
1386 | |||
1387 | This function will convert the given DSA raw parameters | ||
1388 | to the native gnutls_x509_privkey_t format. The output will be stored in @code{key}. | ||
1389 | @end deftypefun | ||
1390 | |||
1391 | @subheading gnutls_x509_privkey_get_pk_algorithm | ||
1392 | @anchor{gnutls_x509_privkey_get_pk_algorithm} | ||
1393 | @deftypefun {int} {gnutls_x509_privkey_get_pk_algorithm} (gnutls_x509_privkey_t @var{key}) | ||
1394 | @var{key}: should contain a gnutls_x509_privkey_t structure | ||
1395 | |||
1396 | This function will return the public key algorithm of a private | ||
1397 | key. | ||
1398 | |||
1399 | Returns a member of the gnutls_pk_algorithm_t enumeration on success, | ||
1400 | or a negative value on error. | ||
1401 | @end deftypefun | ||
1402 | |||
1403 | @subheading gnutls_x509_privkey_export | ||
1404 | @anchor{gnutls_x509_privkey_export} | ||
1405 | @deftypefun {int} {gnutls_x509_privkey_export} (gnutls_x509_privkey_t @var{key}, gnutls_x509_crt_fmt_t @var{format}, void * @var{output_data}, size_t * @var{output_data_size}) | ||
1406 | @var{key}: Holds the key | ||
1407 | |||
1408 | @var{format}: the format of output params. One of PEM or DER. | ||
1409 | |||
1410 | @var{output_data}: will contain a private key PEM or DER encoded | ||
1411 | |||
1412 | @var{output_data_size}: holds the size of output_data (and will be | ||
1413 | replaced by the actual size of parameters) | ||
1414 | |||
1415 | This function will export the private key to a PKCS1 structure for | ||
1416 | RSA keys, or an integer sequence for DSA keys. The DSA keys are in | ||
1417 | the same format with the parameters used by openssl. | ||
1418 | |||
1419 | If the buffer provided is not long enough to hold the output, then | ||
1420 | *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will | ||
1421 | be returned. | ||
1422 | |||
1423 | If the structure is PEM encoded, it will have a header | ||
1424 | of "BEGIN RSA PRIVATE KEY". | ||
1425 | |||
1426 | @strong{Return value:} In case of failure a negative value will be | ||
1427 | returned, and 0 on success. | ||
1428 | @end deftypefun | ||
1429 | |||
1430 | @subheading gnutls_x509_privkey_export_rsa_raw | ||
1431 | @anchor{gnutls_x509_privkey_export_rsa_raw} | ||
1432 | @deftypefun {int} {gnutls_x509_privkey_export_rsa_raw} (gnutls_x509_privkey_t @var{key}, gnutls_datum_t * @var{m}, gnutls_datum_t * @var{e}, gnutls_datum_t * @var{d}, gnutls_datum_t * @var{p}, gnutls_datum_t * @var{q}, gnutls_datum_t * @var{u}) | ||
1433 | @var{key}: a structure that holds the rsa parameters | ||
1434 | |||
1435 | @var{m}: will hold the modulus | ||
1436 | |||
1437 | @var{e}: will hold the public exponent | ||
1438 | |||
1439 | @var{d}: will hold the private exponent | ||
1440 | |||
1441 | @var{p}: will hold the first prime (p) | ||
1442 | |||
1443 | @var{q}: will hold the second prime (q) | ||
1444 | |||
1445 | @var{u}: will hold the coefficient | ||
1446 | |||
1447 | This function will export the RSA private key's parameters found in the given | ||
1448 | structure. The new parameters will be allocated using | ||
1449 | @code{gnutls_malloc()} and will be stored in the appropriate datum. | ||
1450 | @end deftypefun | ||
1451 | |||
1452 | @subheading gnutls_x509_privkey_export_dsa_raw | ||
1453 | @anchor{gnutls_x509_privkey_export_dsa_raw} | ||
1454 | @deftypefun {int} {gnutls_x509_privkey_export_dsa_raw} (gnutls_x509_privkey_t @var{key}, gnutls_datum_t * @var{p}, gnutls_datum_t * @var{q}, gnutls_datum_t * @var{g}, gnutls_datum_t * @var{y}, gnutls_datum_t * @var{x}) | ||
1455 | @var{p}: will hold the p | ||
1456 | |||
1457 | @var{q}: will hold the q | ||
1458 | |||
1459 | @var{g}: will hold the g | ||
1460 | |||
1461 | @var{y}: will hold the y | ||
1462 | |||
1463 | @var{x}: will hold the x | ||
1464 | |||
1465 | This function will export the DSA private key's parameters found in the given | ||
1466 | structure. The new parameters will be allocated using | ||
1467 | @code{gnutls_malloc()} and will be stored in the appropriate datum. | ||
1468 | @end deftypefun | ||
1469 | |||
1470 | @subheading gnutls_x509_privkey_generate | ||
1471 | @anchor{gnutls_x509_privkey_generate} | ||
1472 | @deftypefun {int} {gnutls_x509_privkey_generate} (gnutls_x509_privkey_t @var{key}, gnutls_pk_algorithm_t @var{algo}, unsigned int @var{bits}, unsigned int @var{flags}) | ||
1473 | @var{key}: should contain a gnutls_x509_privkey_t structure | ||
1474 | |||
1475 | @var{algo}: is one of RSA or DSA. | ||
1476 | |||
1477 | @var{bits}: the size of the modulus | ||
1478 | |||
1479 | @var{flags}: unused for now. Must be 0. | ||
1480 | |||
1481 | This function will generate a random private key. Note that | ||
1482 | this function must be called on an empty private key. | ||
1483 | |||
1484 | Returns 0 on success or a negative value on error. | ||
1485 | @end deftypefun | ||
1486 | |||
1487 | @subheading gnutls_x509_privkey_get_key_id | ||
1488 | @anchor{gnutls_x509_privkey_get_key_id} | ||
1489 | @deftypefun {int} {gnutls_x509_privkey_get_key_id} (gnutls_x509_privkey_t @var{key}, unsigned int @var{flags}, unsigned char * @var{output_data}, size_t * @var{output_data_size}) | ||
1490 | @var{key}: Holds the key | ||
1491 | |||
1492 | @var{flags}: should be 0 for now | ||
1493 | |||
1494 | @var{output_data}: will contain the key ID | ||
1495 | |||
1496 | @var{output_data_size}: holds the size of output_data (and will be | ||
1497 | replaced by the actual size of parameters) | ||
1498 | |||
1499 | This function will return a unique ID the depends on the public key | ||
1500 | parameters. This ID can be used in checking whether a certificate | ||
1501 | corresponds to the given key. | ||
1502 | |||
1503 | If the buffer provided is not long enough to hold the output, then | ||
1504 | *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will | ||
1505 | be returned. The output will normally be a SHA-1 hash output, | ||
1506 | which is 20 bytes. | ||
1507 | |||
1508 | @strong{Return value:} In case of failure a negative value will be | ||
1509 | returned, and 0 on success. | ||
1510 | @end deftypefun | ||
1511 | |||
1512 | @subheading gnutls_x509_privkey_sign_data | ||
1513 | @anchor{gnutls_x509_privkey_sign_data} | ||
1514 | @deftypefun {int} {gnutls_x509_privkey_sign_data} (gnutls_x509_privkey_t @var{key}, gnutls_digest_algorithm_t @var{digest}, unsigned int @var{flags}, const gnutls_datum_t * @var{data}, void * @var{signature}, size_t * @var{signature_size}) | ||
1515 | @var{key}: Holds the key | ||
1516 | |||
1517 | @var{digest}: should be MD5 or SHA1 | ||
1518 | |||
1519 | @var{flags}: should be 0 for now | ||
1520 | |||
1521 | @var{data}: holds the data to be signed | ||
1522 | |||
1523 | @var{signature}: will contain the signature | ||
1524 | |||
1525 | @var{signature_size}: holds the size of signature (and will be replaced | ||
1526 | by the new size) | ||
1527 | |||
1528 | This function will sign the given data using a signature algorithm | ||
1529 | supported by the private key. Signature algorithms are always used | ||
1530 | together with a hash functions. Different hash functions may be | ||
1531 | used for the RSA algorithm, but only SHA-1 for the DSA keys. | ||
1532 | |||
1533 | If the buffer provided is not long enough to hold the output, then | ||
1534 | *signature_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will | ||
1535 | be returned. | ||
1536 | |||
1537 | In case of failure a negative value will be returned, and | ||
1538 | 0 on success. | ||
1539 | @end deftypefun | ||
1540 | |||
1541 | @subheading gnutls_x509_privkey_sign_hash | ||
1542 | @anchor{gnutls_x509_privkey_sign_hash} | ||
1543 | @deftypefun {int} {gnutls_x509_privkey_sign_hash} (gnutls_x509_privkey_t @var{key}, const gnutls_datum_t * @var{hash}, gnutls_datum_t * @var{signature}) | ||
1544 | @var{key}: Holds the key | ||
1545 | |||
1546 | @var{hash}: holds the data to be signed | ||
1547 | |||
1548 | @var{signature}: will contain newly allocated signature | ||
1549 | |||
1550 | This function will sign the given hash using the private key. | ||
1551 | |||
1552 | @strong{Return value:} In case of failure a negative value will be returned, | ||
1553 | and 0 on success. | ||
1554 | @end deftypefun | ||
1555 | |||
1556 | @subheading gnutls_x509_privkey_verify_data | ||
1557 | @anchor{gnutls_x509_privkey_verify_data} | ||
1558 | @deftypefun {int} {gnutls_x509_privkey_verify_data} (gnutls_x509_privkey_t @var{key}, unsigned int @var{flags}, const gnutls_datum_t * @var{data}, const gnutls_datum_t * @var{signature}) | ||
1559 | @var{key}: Holds the key | ||
1560 | |||
1561 | @var{flags}: should be 0 for now | ||
1562 | |||
1563 | @var{data}: holds the data to be signed | ||
1564 | |||
1565 | @var{signature}: contains the signature | ||
1566 | |||
1567 | This function will verify the given signed data, using the parameters in the | ||
1568 | private key. | ||
1569 | |||
1570 | In case of a verification failure 0 is returned, and | ||
1571 | 1 on success. | ||
1572 | @end deftypefun | ||
1573 | |||
1574 | @subheading gnutls_x509_privkey_fix | ||
1575 | @anchor{gnutls_x509_privkey_fix} | ||
1576 | @deftypefun {int} {gnutls_x509_privkey_fix} (gnutls_x509_privkey_t @var{key}) | ||
1577 | @var{key}: Holds the key | ||
1578 | |||
1579 | This function will recalculate the secondary parameters in a key. | ||
1580 | In RSA keys, this can be the coefficient and exponent1,2. | ||
1581 | |||
1582 | @strong{Return value:} In case of failure a negative value will be | ||
1583 | returned, and 0 on success. | ||
1584 | @end deftypefun | ||
1585 | |||
1586 | @subheading gnutls_pkcs7_init | ||
1587 | @anchor{gnutls_pkcs7_init} | ||
1588 | @deftypefun {int} {gnutls_pkcs7_init} (gnutls_pkcs7_t * @var{pkcs7}) | ||
1589 | @var{pkcs7}: The structure to be initialized | ||
1590 | |||
1591 | This function will initialize a PKCS7 structure. PKCS7 structures | ||
1592 | usually contain lists of X.509 Certificates and X.509 Certificate | ||
1593 | revocation lists. | ||
1594 | |||
1595 | Returns 0 on success. | ||
1596 | @end deftypefun | ||
1597 | |||
1598 | @subheading gnutls_pkcs7_deinit | ||
1599 | @anchor{gnutls_pkcs7_deinit} | ||
1600 | @deftypefun {void} {gnutls_pkcs7_deinit} (gnutls_pkcs7_t @var{pkcs7}) | ||
1601 | @var{pkcs7}: The structure to be initialized | ||
1602 | |||
1603 | This function will deinitialize a PKCS7 structure. | ||
1604 | @end deftypefun | ||
1605 | |||
1606 | @subheading gnutls_pkcs7_import | ||
1607 | @anchor{gnutls_pkcs7_import} | ||
1608 | @deftypefun {int} {gnutls_pkcs7_import} (gnutls_pkcs7_t @var{pkcs7}, const gnutls_datum_t * @var{data}, gnutls_x509_crt_fmt_t @var{format}) | ||
1609 | @var{pkcs7}: The structure to store the parsed PKCS7. | ||
1610 | |||
1611 | @var{data}: The DER or PEM encoded PKCS7. | ||
1612 | |||
1613 | @var{format}: One of DER or PEM | ||
1614 | |||
1615 | This function will convert the given DER or PEM encoded PKCS7 | ||
1616 | to the native gnutls_pkcs7_t format. The output will be stored in 'pkcs7'. | ||
1617 | |||
1618 | If the PKCS7 is PEM encoded it should have a header of "PKCS7". | ||
1619 | |||
1620 | Returns 0 on success. | ||
1621 | @end deftypefun | ||
1622 | |||
1623 | @subheading gnutls_pkcs7_get_crt_raw | ||
1624 | @anchor{gnutls_pkcs7_get_crt_raw} | ||
1625 | @deftypefun {int} {gnutls_pkcs7_get_crt_raw} (gnutls_pkcs7_t @var{pkcs7}, int @var{indx}, void * @var{certificate}, size_t * @var{certificate_size}) | ||
1626 | @var{indx}: contains the index of the certificate to extract | ||
1627 | |||
1628 | @var{certificate}: the contents of the certificate will be copied there (may be null) | ||
1629 | |||
1630 | @var{certificate_size}: should hold the size of the certificate | ||
1631 | |||
1632 | This function will return a certificate of the PKCS7 or RFC2630 certificate set. | ||
1633 | Returns 0 on success. If the provided buffer is not long enough, | ||
1634 | then @code{certificate_size} is updated and GNUTLS_E_SHORT_MEMORY_BUFFER is returned. | ||
1635 | |||
1636 | After the last certificate has been read GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE | ||
1637 | will be returned. | ||
1638 | @end deftypefun | ||
1639 | |||
1640 | @subheading gnutls_pkcs7_get_crt_count | ||
1641 | @anchor{gnutls_pkcs7_get_crt_count} | ||
1642 | @deftypefun {int} {gnutls_pkcs7_get_crt_count} (gnutls_pkcs7_t @var{pkcs7}) | ||
1643 | This function will return the number of certifcates in the PKCS7 or | ||
1644 | RFC2630 certificate set. | ||
1645 | |||
1646 | Returns a negative value on failure. | ||
1647 | @end deftypefun | ||
1648 | |||
1649 | @subheading gnutls_pkcs7_export | ||
1650 | @anchor{gnutls_pkcs7_export} | ||
1651 | @deftypefun {int} {gnutls_pkcs7_export} (gnutls_pkcs7_t @var{pkcs7}, gnutls_x509_crt_fmt_t @var{format}, void * @var{output_data}, size_t * @var{output_data_size}) | ||
1652 | @var{pkcs7}: Holds the pkcs7 structure | ||
1653 | |||
1654 | @var{format}: the format of output params. One of PEM or DER. | ||
1655 | |||
1656 | @var{output_data}: will contain a structure PEM or DER encoded | ||
1657 | |||
1658 | @var{output_data_size}: holds the size of output_data (and will be | ||
1659 | replaced by the actual size of parameters) | ||
1660 | |||
1661 | This function will export the pkcs7 structure to DER or PEM format. | ||
1662 | |||
1663 | If the buffer provided is not long enough to hold the output, then | ||
1664 | *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will | ||
1665 | be returned. | ||
1666 | |||
1667 | If the structure is PEM encoded, it will have a header | ||
1668 | of "BEGIN PKCS7". | ||
1669 | |||
1670 | @strong{Return value:} In case of failure a negative value will be | ||
1671 | returned, and 0 on success. | ||
1672 | @end deftypefun | ||
1673 | |||
1674 | @subheading gnutls_pkcs7_set_crt_raw | ||
1675 | @anchor{gnutls_pkcs7_set_crt_raw} | ||
1676 | @deftypefun {int} {gnutls_pkcs7_set_crt_raw} (gnutls_pkcs7_t @var{pkcs7}, const gnutls_datum_t * @var{crt}) | ||
1677 | @var{crt}: the DER encoded certificate to be added | ||
1678 | |||
1679 | This function will add a certificate to the PKCS7 or RFC2630 certificate set. | ||
1680 | Returns 0 on success. | ||
1681 | @end deftypefun | ||
1682 | |||
1683 | @subheading gnutls_pkcs7_set_crt | ||
1684 | @anchor{gnutls_pkcs7_set_crt} | ||
1685 | @deftypefun {int} {gnutls_pkcs7_set_crt} (gnutls_pkcs7_t @var{pkcs7}, gnutls_x509_crt_t @var{crt}) | ||
1686 | @var{crt}: the certificate to be copied. | ||
1687 | |||
1688 | This function will add a parsed certificate to the PKCS7 or RFC2630 certificate set. | ||
1689 | This is a wrapper function over @code{gnutls_pkcs7_set_crt_raw()} . | ||
1690 | |||
1691 | Returns 0 on success. | ||
1692 | @end deftypefun | ||
1693 | |||
1694 | @subheading gnutls_pkcs7_delete_crt | ||
1695 | @anchor{gnutls_pkcs7_delete_crt} | ||
1696 | @deftypefun {int} {gnutls_pkcs7_delete_crt} (gnutls_pkcs7_t @var{pkcs7}, int @var{indx}) | ||
1697 | @var{indx}: the index of the certificate to delete | ||
1698 | |||
1699 | This function will delete a certificate from a PKCS7 or RFC2630 certificate set. | ||
1700 | Index starts from 0. Returns 0 on success. | ||
1701 | @end deftypefun | ||
1702 | |||
1703 | @subheading gnutls_pkcs7_get_crl_raw | ||
1704 | @anchor{gnutls_pkcs7_get_crl_raw} | ||
1705 | @deftypefun {int} {gnutls_pkcs7_get_crl_raw} (gnutls_pkcs7_t @var{pkcs7}, int @var{indx}, void * @var{crl}, size_t * @var{crl_size}) | ||
1706 | @var{indx}: contains the index of the crl to extract | ||
1707 | |||
1708 | @var{crl}: the contents of the crl will be copied there (may be null) | ||
1709 | |||
1710 | @var{crl_size}: should hold the size of the crl | ||
1711 | |||
1712 | This function will return a crl of the PKCS7 or RFC2630 crl set. | ||
1713 | Returns 0 on success. If the provided buffer is not long enough, | ||
1714 | then @code{crl_size} is updated and GNUTLS_E_SHORT_MEMORY_BUFFER is returned. | ||
1715 | |||
1716 | After the last crl has been read GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE | ||
1717 | will be returned. | ||
1718 | @end deftypefun | ||
1719 | |||
1720 | @subheading gnutls_pkcs7_get_crl_count | ||
1721 | @anchor{gnutls_pkcs7_get_crl_count} | ||
1722 | @deftypefun {int} {gnutls_pkcs7_get_crl_count} (gnutls_pkcs7_t @var{pkcs7}) | ||
1723 | This function will return the number of certifcates in the PKCS7 or | ||
1724 | RFC2630 crl set. | ||
1725 | |||
1726 | Returns a negative value on failure. | ||
1727 | @end deftypefun | ||
1728 | |||
1729 | @subheading gnutls_pkcs7_set_crl_raw | ||
1730 | @anchor{gnutls_pkcs7_set_crl_raw} | ||
1731 | @deftypefun {int} {gnutls_pkcs7_set_crl_raw} (gnutls_pkcs7_t @var{pkcs7}, const gnutls_datum_t * @var{crl}) | ||
1732 | @var{crl}: the DER encoded crl to be added | ||
1733 | |||
1734 | This function will add a crl to the PKCS7 or RFC2630 crl set. | ||
1735 | Returns 0 on success. | ||
1736 | @end deftypefun | ||
1737 | |||
1738 | @subheading gnutls_pkcs7_set_crl | ||
1739 | @anchor{gnutls_pkcs7_set_crl} | ||
1740 | @deftypefun {int} {gnutls_pkcs7_set_crl} (gnutls_pkcs7_t @var{pkcs7}, gnutls_x509_crl_t @var{crl}) | ||
1741 | @var{crl}: the DER encoded crl to be added | ||
1742 | |||
1743 | This function will add a parsed crl to the PKCS7 or RFC2630 crl set. | ||
1744 | Returns 0 on success. | ||
1745 | @end deftypefun | ||
1746 | |||
1747 | @subheading gnutls_pkcs7_delete_crl | ||
1748 | @anchor{gnutls_pkcs7_delete_crl} | ||
1749 | @deftypefun {int} {gnutls_pkcs7_delete_crl} (gnutls_pkcs7_t @var{pkcs7}, int @var{indx}) | ||
1750 | @var{indx}: the index of the crl to delete | ||
1751 | |||
1752 | This function will delete a crl from a PKCS7 or RFC2630 crl set. | ||
1753 | Index starts from 0. Returns 0 on success. | ||
1754 | @end deftypefun | ||
1755 | |||
1756 | @subheading gnutls_x509_crq_init | ||
1757 | @anchor{gnutls_x509_crq_init} | ||
1758 | @deftypefun {int} {gnutls_x509_crq_init} (gnutls_x509_crq_t * @var{crq}) | ||
1759 | @var{crq}: The structure to be initialized | ||
1760 | |||
1761 | This function will initialize a PKCS10 certificate request structure. | ||
1762 | |||
1763 | Returns 0 on success. | ||
1764 | @end deftypefun | ||
1765 | |||
1766 | @subheading gnutls_x509_crq_deinit | ||
1767 | @anchor{gnutls_x509_crq_deinit} | ||
1768 | @deftypefun {void} {gnutls_x509_crq_deinit} (gnutls_x509_crq_t @var{crq}) | ||
1769 | @var{crq}: The structure to be initialized | ||
1770 | |||
1771 | This function will deinitialize a CRL structure. | ||
1772 | @end deftypefun | ||
1773 | |||
1774 | @subheading gnutls_x509_crq_import | ||
1775 | @anchor{gnutls_x509_crq_import} | ||
1776 | @deftypefun {int} {gnutls_x509_crq_import} (gnutls_x509_crq_t @var{crq}, const gnutls_datum_t * @var{data}, gnutls_x509_crt_fmt_t @var{format}) | ||
1777 | @var{crq}: The structure to store the parsed certificate request. | ||
1778 | |||
1779 | @var{data}: The DER or PEM encoded certificate. | ||
1780 | |||
1781 | @var{format}: One of DER or PEM | ||
1782 | |||
1783 | This function will convert the given DER or PEM encoded Certificate | ||
1784 | to the native gnutls_x509_crq_t format. The output will be stored in @code{cert}. | ||
1785 | |||
1786 | If the Certificate is PEM encoded it should have a header of "NEW CERTIFICATE REQUEST". | ||
1787 | |||
1788 | Returns 0 on success. | ||
1789 | @end deftypefun | ||
1790 | |||
1791 | @subheading gnutls_x509_crq_get_dn | ||
1792 | @anchor{gnutls_x509_crq_get_dn} | ||
1793 | @deftypefun {int} {gnutls_x509_crq_get_dn} (gnutls_x509_crq_t @var{crq}, char * @var{buf}, size_t * @var{sizeof_buf}) | ||
1794 | @var{crq}: should contain a gnutls_x509_crq_t structure | ||
1795 | |||
1796 | @var{buf}: a pointer to a structure to hold the name (may be null) | ||
1797 | |||
1798 | @var{sizeof_buf}: initially holds the size of @code{buf} | ||
1799 | |||
1800 | This function will copy the name of the Certificate request | ||
1801 | subject in the provided buffer. The name will be in the form | ||
1802 | "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253. The output string | ||
1803 | will be ASCII or UTF-8 encoded, depending on the certificate data. | ||
1804 | |||
1805 | If @code{buf} is null then only the size will be filled. | ||
1806 | |||
1807 | Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not | ||
1808 | long enough, and in that case the *sizeof_buf will be updated with | ||
1809 | the required size. On success 0 is returned. | ||
1810 | @end deftypefun | ||
1811 | |||
1812 | @subheading gnutls_x509_crq_get_dn_by_oid | ||
1813 | @anchor{gnutls_x509_crq_get_dn_by_oid} | ||
1814 | @deftypefun {int} {gnutls_x509_crq_get_dn_by_oid} (gnutls_x509_crq_t @var{crq}, const char * @var{oid}, int @var{indx}, unsigned int @var{raw_flag}, void * @var{buf}, size_t * @var{sizeof_buf}) | ||
1815 | @var{crq}: should contain a gnutls_x509_crq_t structure | ||
1816 | |||
1817 | @var{oid}: holds an Object Identified in null terminated string | ||
1818 | |||
1819 | @var{indx}: In case multiple same OIDs exist in the RDN, this specifies | ||
1820 | which to send. Use zero to get the first one. | ||
1821 | |||
1822 | @var{raw_flag}: If non zero returns the raw DER data of the DN part. | ||
1823 | |||
1824 | @var{buf}: a pointer to a structure to hold the name (may be null) | ||
1825 | |||
1826 | @var{sizeof_buf}: initially holds the size of @code{buf} | ||
1827 | |||
1828 | This function will extract the part of the name of the Certificate | ||
1829 | request subject, specified by the given OID. The output will be | ||
1830 | encoded as described in RFC2253. The output string will be ASCII | ||
1831 | or UTF-8 encoded, depending on the certificate data. | ||
1832 | |||
1833 | Some helper macros with popular OIDs can be found in gnutls/x509.h | ||
1834 | If raw flag is zero, this function will only return known OIDs as | ||
1835 | text. Other OIDs will be DER encoded, as described in RFC2253 -- | ||
1836 | in hex format with a '\#' prefix. You can check about known OIDs | ||
1837 | using @code{gnutls_x509_dn_oid_known()}. | ||
1838 | |||
1839 | If @code{buf} is null then only the size will be filled. | ||
1840 | |||
1841 | Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not | ||
1842 | long enough, and in that case the *sizeof_buf will be updated with | ||
1843 | the required size. On success 0 is returned. | ||
1844 | @end deftypefun | ||
1845 | |||
1846 | @subheading gnutls_x509_crq_get_dn_oid | ||
1847 | @anchor{gnutls_x509_crq_get_dn_oid} | ||
1848 | @deftypefun {int} {gnutls_x509_crq_get_dn_oid} (gnutls_x509_crq_t @var{crq}, int @var{indx}, void * @var{oid}, size_t * @var{sizeof_oid}) | ||
1849 | @var{crq}: should contain a gnutls_x509_crq_t structure | ||
1850 | |||
1851 | @var{indx}: Specifies which DN OID to send. Use zero to get the first one. | ||
1852 | |||
1853 | @var{oid}: a pointer to a structure to hold the name (may be null) | ||
1854 | |||
1855 | @var{sizeof_oid}: initially holds the size of @code{oid} | ||
1856 | |||
1857 | This function will extract the requested OID of the name of the | ||
1858 | Certificate request subject, specified by the given index. | ||
1859 | |||
1860 | If oid is null then only the size will be filled. | ||
1861 | |||
1862 | Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not | ||
1863 | long enough, and in that case the *sizeof_oid will be updated with | ||
1864 | the required size. On success 0 is returned. | ||
1865 | @end deftypefun | ||
1866 | |||
1867 | @subheading gnutls_x509_crq_get_challenge_password | ||
1868 | @anchor{gnutls_x509_crq_get_challenge_password} | ||
1869 | @deftypefun {int} {gnutls_x509_crq_get_challenge_password} (gnutls_x509_crq_t @var{crq}, char * @var{pass}, size_t * @var{sizeof_pass}) | ||
1870 | @var{crq}: should contain a gnutls_x509_crq_t structure | ||
1871 | |||
1872 | @var{pass}: will hold a null terminated password | ||
1873 | |||
1874 | @var{sizeof_pass}: Initially holds the size of @code{pass}. | ||
1875 | |||
1876 | This function will return the challenge password in the | ||
1877 | request. | ||
1878 | |||
1879 | Returns 0 on success. | ||
1880 | @end deftypefun | ||
1881 | |||
1882 | @subheading gnutls_x509_crq_set_attribute_by_oid | ||
1883 | @anchor{gnutls_x509_crq_set_attribute_by_oid} | ||
1884 | @deftypefun {int} {gnutls_x509_crq_set_attribute_by_oid} (gnutls_x509_crq_t @var{crq}, const char * @var{oid}, void * @var{buf}, size_t @var{sizeof_buf}) | ||
1885 | @var{crq}: should contain a gnutls_x509_crq_t structure | ||
1886 | |||
1887 | @var{oid}: holds an Object Identified in null terminated string | ||
1888 | |||
1889 | @var{buf}: a pointer to a structure that holds the attribute data | ||
1890 | |||
1891 | @var{sizeof_buf}: holds the size of @code{buf} | ||
1892 | |||
1893 | This function will set the attribute in the certificate request specified | ||
1894 | by the given Object ID. The attribute must be be DER encoded. | ||
1895 | |||
1896 | Returns 0 on success. | ||
1897 | @end deftypefun | ||
1898 | |||
1899 | @subheading gnutls_x509_crq_get_attribute_by_oid | ||
1900 | @anchor{gnutls_x509_crq_get_attribute_by_oid} | ||
1901 | @deftypefun {int} {gnutls_x509_crq_get_attribute_by_oid} (gnutls_x509_crq_t @var{crq}, const char * @var{oid}, int @var{indx}, void * @var{buf}, size_t * @var{sizeof_buf}) | ||
1902 | @var{crq}: should contain a gnutls_x509_crq_t structure | ||
1903 | |||
1904 | @var{oid}: holds an Object Identified in null terminated string | ||
1905 | |||
1906 | @var{indx}: In case multiple same OIDs exist in the attribute list, this specifies | ||
1907 | which to send. Use zero to get the first one. | ||
1908 | |||
1909 | @var{buf}: a pointer to a structure to hold the attribute data (may be null) | ||
1910 | |||
1911 | @var{sizeof_buf}: initially holds the size of @code{buf} | ||
1912 | |||
1913 | This function will return the attribute in the certificate request specified | ||
1914 | by the given Object ID. The attribute will be DER encoded. | ||
1915 | |||
1916 | Returns 0 on success. | ||
1917 | @end deftypefun | ||
1918 | |||
1919 | @subheading gnutls_x509_crq_set_dn_by_oid | ||
1920 | @anchor{gnutls_x509_crq_set_dn_by_oid} | ||
1921 | @deftypefun {int} {gnutls_x509_crq_set_dn_by_oid} (gnutls_x509_crq_t @var{crq}, const char * @var{oid}, unsigned int @var{raw_flag}, const void * @var{data}, unsigned int @var{sizeof_data}) | ||
1922 | @var{crq}: should contain a gnutls_x509_crq_t structure | ||
1923 | |||
1924 | @var{oid}: holds an Object Identifier in a null terminated string | ||
1925 | |||
1926 | @var{raw_flag}: must be 0, or 1 if the data are DER encoded | ||
1927 | |||
1928 | @var{data}: a pointer to the input data | ||
1929 | |||
1930 | @var{sizeof_data}: holds the size of @code{data} | ||
1931 | |||
1932 | This function will set the part of the name of the Certificate request subject, specified | ||
1933 | by the given OID. The input string should be ASCII or UTF-8 encoded. | ||
1934 | |||
1935 | Some helper macros with popular OIDs can be found in gnutls/x509.h | ||
1936 | With this function you can only set the known OIDs. You can test | ||
1937 | for known OIDs using @code{gnutls_x509_dn_oid_known()}. For OIDs that are | ||
1938 | not known (by gnutls) you should properly DER encode your data, and | ||
1939 | call this function with raw_flag set. | ||
1940 | |||
1941 | Returns 0 on success. | ||
1942 | @end deftypefun | ||
1943 | |||
1944 | @subheading gnutls_x509_crq_set_version | ||
1945 | @anchor{gnutls_x509_crq_set_version} | ||
1946 | @deftypefun {int} {gnutls_x509_crq_set_version} (gnutls_x509_crq_t @var{crq}, unsigned int @var{version}) | ||
1947 | @var{crq}: should contain a gnutls_x509_crq_t structure | ||
1948 | |||
1949 | @var{version}: holds the version number. For v1 Requests must be 1. | ||
1950 | |||
1951 | This function will set the version of the certificate request. For | ||
1952 | version 1 requests this must be one. | ||
1953 | |||
1954 | Returns 0 on success. | ||
1955 | @end deftypefun | ||
1956 | |||
1957 | @subheading gnutls_x509_crq_get_version | ||
1958 | @anchor{gnutls_x509_crq_get_version} | ||
1959 | @deftypefun {int} {gnutls_x509_crq_get_version} (gnutls_x509_crq_t @var{crq}) | ||
1960 | @var{crq}: should contain a gnutls_x509_crq_t structure | ||
1961 | |||
1962 | This function will return the version of the specified Certificate request. | ||
1963 | |||
1964 | Returns a negative value on error. | ||
1965 | @end deftypefun | ||
1966 | |||
1967 | @subheading gnutls_x509_crq_set_key | ||
1968 | @anchor{gnutls_x509_crq_set_key} | ||
1969 | @deftypefun {int} {gnutls_x509_crq_set_key} (gnutls_x509_crq_t @var{crq}, gnutls_x509_privkey_t @var{key}) | ||
1970 | @var{crq}: should contain a gnutls_x509_crq_t structure | ||
1971 | |||
1972 | @var{key}: holds a private key | ||
1973 | |||
1974 | This function will set the public parameters from the given private key to the | ||
1975 | request. Only RSA keys are currently supported. | ||
1976 | |||
1977 | Returns 0 on success. | ||
1978 | @end deftypefun | ||
1979 | |||
1980 | @subheading gnutls_x509_crq_set_challenge_password | ||
1981 | @anchor{gnutls_x509_crq_set_challenge_password} | ||
1982 | @deftypefun {int} {gnutls_x509_crq_set_challenge_password} (gnutls_x509_crq_t @var{crq}, const char * @var{pass}) | ||
1983 | @var{crq}: should contain a gnutls_x509_crq_t structure | ||
1984 | |||
1985 | @var{pass}: holds a null terminated password | ||
1986 | |||
1987 | This function will set a challenge password to be used when revoking the request. | ||
1988 | |||
1989 | Returns 0 on success. | ||
1990 | @end deftypefun | ||
1991 | |||
1992 | @subheading gnutls_x509_crq_sign2 | ||
1993 | @anchor{gnutls_x509_crq_sign2} | ||
1994 | @deftypefun {int} {gnutls_x509_crq_sign2} (gnutls_x509_crq_t @var{crq}, gnutls_x509_privkey_t @var{key}, gnutls_digest_algorithm_t @var{dig}, unsigned int @var{flags}) | ||
1995 | @var{crq}: should contain a gnutls_x509_crq_t structure | ||
1996 | |||
1997 | @var{key}: holds a private key | ||
1998 | |||
1999 | @var{dig}: The message digest to use. GNUTLS_DIG_SHA1 is the safe choice unless you know what you're doing. | ||
2000 | |||
2001 | @var{flags}: must be 0 | ||
2002 | |||
2003 | This function will sign the certificate request with a private key. | ||
2004 | This must be the same key as the one used in @code{gnutls_x509_crt_set_key()} since a | ||
2005 | certificate request is self signed. | ||
2006 | |||
2007 | This must be the last step in a certificate request generation since all | ||
2008 | the previously set parameters are now signed. | ||
2009 | |||
2010 | Returns 0 on success. | ||
2011 | @end deftypefun | ||
2012 | |||
2013 | @subheading gnutls_x509_crq_sign | ||
2014 | @anchor{gnutls_x509_crq_sign} | ||
2015 | @deftypefun {int} {gnutls_x509_crq_sign} (gnutls_x509_crq_t @var{crq}, gnutls_x509_privkey_t @var{key}) | ||
2016 | @var{crq}: should contain a gnutls_x509_crq_t structure | ||
2017 | |||
2018 | @var{key}: holds a private key | ||
2019 | |||
2020 | This function is the same a @code{gnutls_x509_crq_sign2()} with no flags, and | ||
2021 | SHA1 as the hash algorithm. | ||
2022 | |||
2023 | Returns 0 on success. | ||
2024 | @end deftypefun | ||
2025 | |||
2026 | @subheading gnutls_x509_crq_export | ||
2027 | @anchor{gnutls_x509_crq_export} | ||
2028 | @deftypefun {int} {gnutls_x509_crq_export} (gnutls_x509_crq_t @var{crq}, gnutls_x509_crt_fmt_t @var{format}, void * @var{output_data}, size_t * @var{output_data_size}) | ||
2029 | @var{crq}: Holds the request | ||
2030 | |||
2031 | @var{format}: the format of output params. One of PEM or DER. | ||
2032 | |||
2033 | @var{output_data}: will contain a certificate request PEM or DER encoded | ||
2034 | |||
2035 | @var{output_data_size}: holds the size of output_data (and will be | ||
2036 | replaced by the actual size of parameters) | ||
2037 | |||
2038 | This function will export the certificate request to a PKCS10 | ||
2039 | |||
2040 | If the buffer provided is not long enough to hold the output, then | ||
2041 | GNUTLS_E_SHORT_MEMORY_BUFFER will be returned and | ||
2042 | *output_data_size will be updated. | ||
2043 | |||
2044 | If the structure is PEM encoded, it will have a header of "BEGIN | ||
2045 | NEW CERTIFICATE REQUEST". | ||
2046 | |||
2047 | @strong{Return value:} In case of failure a negative value will be | ||
2048 | returned, and 0 on success. | ||
2049 | @end deftypefun | ||
2050 | |||
2051 | @subheading gnutls_x509_crq_get_pk_algorithm | ||
2052 | @anchor{gnutls_x509_crq_get_pk_algorithm} | ||
2053 | @deftypefun {int} {gnutls_x509_crq_get_pk_algorithm} (gnutls_x509_crq_t @var{crq}, unsigned int * @var{bits}) | ||
2054 | @var{crq}: should contain a gnutls_x509_crq_t structure | ||
2055 | |||
2056 | @var{bits}: if bits is non null it will hold the size of the parameters' in bits | ||
2057 | |||
2058 | This function will return the public key algorithm of a PKCS \@code{10} | ||
2059 | certificate request. | ||
2060 | |||
2061 | If bits is non null, it should have enough size to hold the parameters | ||
2062 | size in bits. For RSA the bits returned is the modulus. | ||
2063 | For DSA the bits returned are of the public | ||
2064 | exponent. | ||
2065 | |||
2066 | Returns a member of the gnutls_pk_algorithm_t enumeration on success, | ||
2067 | or a negative value on error. | ||
2068 | @end deftypefun | ||
2069 | |||
2070 | @subheading gnutls_x509_privkey_export_pkcs8 | ||
2071 | @anchor{gnutls_x509_privkey_export_pkcs8} | ||
2072 | @deftypefun {int} {gnutls_x509_privkey_export_pkcs8} (gnutls_x509_privkey_t @var{key}, gnutls_x509_crt_fmt_t @var{format}, const char * @var{password}, unsigned int @var{flags}, void * @var{output_data}, size_t * @var{output_data_size}) | ||
2073 | @var{key}: Holds the key | ||
2074 | |||
2075 | @var{format}: the format of output params. One of PEM or DER. | ||
2076 | |||
2077 | @var{password}: the password that will be used to encrypt the key. | ||
2078 | |||
2079 | @var{flags}: an ORed sequence of gnutls_pkcs_encrypt_flags_t | ||
2080 | |||
2081 | @var{output_data}: will contain a private key PEM or DER encoded | ||
2082 | |||
2083 | @var{output_data_size}: holds the size of output_data (and will be | ||
2084 | replaced by the actual size of parameters) | ||
2085 | |||
2086 | This function will export the private key to a PKCS8 structure. | ||
2087 | Both RSA and DSA keys can be exported. For DSA keys we use | ||
2088 | PKCS @code{11} definitions. If the flags do not specify the encryption | ||
2089 | cipher, then the default 3DES (PBES2) will be used. | ||
2090 | |||
2091 | The @code{password} can be either ASCII or UTF-8 in the default PBES2 | ||
2092 | encryption schemas, or ASCII for the PKCS12 schemas. | ||
2093 | |||
2094 | If the buffer provided is not long enough to hold the output, then | ||
2095 | *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will | ||
2096 | be returned. | ||
2097 | |||
2098 | If the structure is PEM encoded, it will have a header | ||
2099 | of "BEGIN ENCRYPTED PRIVATE KEY" or "BEGIN PRIVATE KEY" if | ||
2100 | encryption is not used. | ||
2101 | |||
2102 | @strong{Return value:} In case of failure a negative value will be | ||
2103 | returned, and 0 on success. | ||
2104 | @end deftypefun | ||
2105 | |||
2106 | @subheading gnutls_x509_privkey_import_pkcs8 | ||
2107 | @anchor{gnutls_x509_privkey_import_pkcs8} | ||
2108 | @deftypefun {int} {gnutls_x509_privkey_import_pkcs8} (gnutls_x509_privkey_t @var{key}, const gnutls_datum_t * @var{data}, gnutls_x509_crt_fmt_t @var{format}, const char * @var{password}, unsigned int @var{flags}) | ||
2109 | @var{key}: The structure to store the parsed key | ||
2110 | |||
2111 | @var{data}: The DER or PEM encoded key. | ||
2112 | |||
2113 | @var{format}: One of DER or PEM | ||
2114 | |||
2115 | @var{password}: the password to decrypt the key (if it is encrypted). | ||
2116 | |||
2117 | @var{flags}: 0 if encrypted or GNUTLS_PKCS_PLAIN if not encrypted. | ||
2118 | |||
2119 | This function will convert the given DER or PEM encoded PKCS8 2.0 encrypted key | ||
2120 | to the native gnutls_x509_privkey_t format. The output will be stored in @code{key}. | ||
2121 | Both RSA and DSA keys can be imported, and flags can only be used to indicate | ||
2122 | an unencrypted key. | ||
2123 | |||
2124 | The @code{password} can be either ASCII or UTF-8 in the default PBES2 | ||
2125 | encryption schemas, or ASCII for the PKCS12 schemas. | ||
2126 | |||
2127 | If the Certificate is PEM encoded it should have a header of "ENCRYPTED PRIVATE KEY", | ||
2128 | or "PRIVATE KEY". You only need to specify the flags if the key is DER encoded, since | ||
2129 | in that case the encryption status cannot be auto-detected. | ||
2130 | |||
2131 | Returns 0 on success. | ||
2132 | @end deftypefun | ||
2133 | |||
2134 | @subheading gnutls_pkcs12_init | ||
2135 | @anchor{gnutls_pkcs12_init} | ||
2136 | @deftypefun {int} {gnutls_pkcs12_init} (gnutls_pkcs12_t * @var{pkcs12}) | ||
2137 | @var{pkcs12}: The structure to be initialized | ||
2138 | |||
2139 | This function will initialize a PKCS12 structure. PKCS12 structures | ||
2140 | usually contain lists of X.509 Certificates and X.509 Certificate | ||
2141 | revocation lists. | ||
2142 | |||
2143 | Returns 0 on success. | ||
2144 | @end deftypefun | ||
2145 | |||
2146 | @subheading gnutls_pkcs12_deinit | ||
2147 | @anchor{gnutls_pkcs12_deinit} | ||
2148 | @deftypefun {void} {gnutls_pkcs12_deinit} (gnutls_pkcs12_t @var{pkcs12}) | ||
2149 | @var{pkcs12}: The structure to be initialized | ||
2150 | |||
2151 | This function will deinitialize a PKCS12 structure. | ||
2152 | @end deftypefun | ||
2153 | |||
2154 | @subheading gnutls_pkcs12_import | ||
2155 | @anchor{gnutls_pkcs12_import} | ||
2156 | @deftypefun {int} {gnutls_pkcs12_import} (gnutls_pkcs12_t @var{pkcs12}, const gnutls_datum_t * @var{data}, gnutls_x509_crt_fmt_t @var{format}, unsigned int @var{flags}) | ||
2157 | @var{pkcs12}: The structure to store the parsed PKCS12. | ||
2158 | |||
2159 | @var{data}: The DER or PEM encoded PKCS12. | ||
2160 | |||
2161 | @var{format}: One of DER or PEM | ||
2162 | |||
2163 | @var{flags}: an ORed sequence of gnutls_privkey_pkcs8_flags | ||
2164 | |||
2165 | This function will convert the given DER or PEM encoded PKCS12 | ||
2166 | to the native gnutls_pkcs12_t format. The output will be stored in 'pkcs12'. | ||
2167 | |||
2168 | If the PKCS12 is PEM encoded it should have a header of "PKCS12". | ||
2169 | |||
2170 | Returns 0 on success. | ||
2171 | @end deftypefun | ||
2172 | |||
2173 | @subheading gnutls_pkcs12_export | ||
2174 | @anchor{gnutls_pkcs12_export} | ||
2175 | @deftypefun {int} {gnutls_pkcs12_export} (gnutls_pkcs12_t @var{pkcs12}, gnutls_x509_crt_fmt_t @var{format}, void * @var{output_data}, size_t * @var{output_data_size}) | ||
2176 | @var{pkcs12}: Holds the pkcs12 structure | ||
2177 | |||
2178 | @var{format}: the format of output params. One of PEM or DER. | ||
2179 | |||
2180 | @var{output_data}: will contain a structure PEM or DER encoded | ||
2181 | |||
2182 | @var{output_data_size}: holds the size of output_data (and will be | ||
2183 | replaced by the actual size of parameters) | ||
2184 | |||
2185 | This function will export the pkcs12 structure to DER or PEM format. | ||
2186 | |||
2187 | If the buffer provided is not long enough to hold the output, then | ||
2188 | *output_data_size will be updated and GNUTLS_E_SHORT_MEMORY_BUFFER | ||
2189 | will be returned. | ||
2190 | |||
2191 | If the structure is PEM encoded, it will have a header | ||
2192 | of "BEGIN PKCS12". | ||
2193 | |||
2194 | @strong{Return value:} In case of failure a negative value will be | ||
2195 | returned, and 0 on success. | ||
2196 | @end deftypefun | ||
2197 | |||
2198 | @subheading gnutls_pkcs12_get_bag | ||
2199 | @anchor{gnutls_pkcs12_get_bag} | ||
2200 | @deftypefun {int} {gnutls_pkcs12_get_bag} (gnutls_pkcs12_t @var{pkcs12}, int @var{indx}, gnutls_pkcs12_bag_t @var{bag}) | ||
2201 | @var{pkcs12}: should contain a gnutls_pkcs12_t structure | ||
2202 | |||
2203 | @var{indx}: contains the index of the bag to extract | ||
2204 | |||
2205 | @var{bag}: An initialized bag, where the contents of the bag will be copied | ||
2206 | |||
2207 | This function will return a Bag from the PKCS12 structure. | ||
2208 | Returns 0 on success. | ||
2209 | |||
2210 | After the last Bag has been read GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE | ||
2211 | will be returned. | ||
2212 | @end deftypefun | ||
2213 | |||
2214 | @subheading gnutls_pkcs12_set_bag | ||
2215 | @anchor{gnutls_pkcs12_set_bag} | ||
2216 | @deftypefun {int} {gnutls_pkcs12_set_bag} (gnutls_pkcs12_t @var{pkcs12}, gnutls_pkcs12_bag_t @var{bag}) | ||
2217 | @var{pkcs12}: should contain a gnutls_pkcs12_t structure | ||
2218 | |||
2219 | @var{bag}: An initialized bag | ||
2220 | |||
2221 | This function will insert a Bag into the PKCS12 structure. | ||
2222 | Returns 0 on success. | ||
2223 | @end deftypefun | ||
2224 | |||
2225 | @subheading gnutls_pkcs12_generate_mac | ||
2226 | @anchor{gnutls_pkcs12_generate_mac} | ||
2227 | @deftypefun {int} {gnutls_pkcs12_generate_mac} (gnutls_pkcs12_t @var{pkcs12}, const char * @var{pass}) | ||
2228 | @var{pkcs12}: should contain a gnutls_pkcs12_t structure | ||
2229 | |||
2230 | @var{pass}: The password for the MAC | ||
2231 | |||
2232 | This function will generate a MAC for the PKCS12 structure. | ||
2233 | Returns 0 on success. | ||
2234 | @end deftypefun | ||
2235 | |||
2236 | @subheading gnutls_pkcs12_verify_mac | ||
2237 | @anchor{gnutls_pkcs12_verify_mac} | ||
2238 | @deftypefun {int} {gnutls_pkcs12_verify_mac} (gnutls_pkcs12_t @var{pkcs12}, const char * @var{pass}) | ||
2239 | @var{pkcs12}: should contain a gnutls_pkcs12_t structure | ||
2240 | |||
2241 | @var{pass}: The password for the MAC | ||
2242 | |||
2243 | This function will verify the MAC for the PKCS12 structure. | ||
2244 | Returns 0 on success. | ||
2245 | @end deftypefun | ||
2246 | |||
2247 | @subheading gnutls_pkcs12_bag_init | ||
2248 | @anchor{gnutls_pkcs12_bag_init} | ||
2249 | @deftypefun {int} {gnutls_pkcs12_bag_init} (gnutls_pkcs12_bag_t * @var{bag}) | ||
2250 | @var{bag}: The structure to be initialized | ||
2251 | |||
2252 | This function will initialize a PKCS12 bag structure. PKCS12 Bags | ||
2253 | usually contain private keys, lists of X.509 Certificates and X.509 Certificate | ||
2254 | revocation lists. | ||
2255 | |||
2256 | Returns 0 on success. | ||
2257 | @end deftypefun | ||
2258 | |||
2259 | @subheading gnutls_pkcs12_bag_deinit | ||
2260 | @anchor{gnutls_pkcs12_bag_deinit} | ||
2261 | @deftypefun {void} {gnutls_pkcs12_bag_deinit} (gnutls_pkcs12_bag_t @var{bag}) | ||
2262 | @var{bag}: The structure to be initialized | ||
2263 | |||
2264 | This function will deinitialize a PKCS12 Bag structure. | ||
2265 | @end deftypefun | ||
2266 | |||
2267 | @subheading gnutls_pkcs12_bag_get_type | ||
2268 | @anchor{gnutls_pkcs12_bag_get_type} | ||
2269 | @deftypefun {gnutls_pkcs12_bag_type_t} {gnutls_pkcs12_bag_get_type} (gnutls_pkcs12_bag_t @var{bag}, int @var{indx}) | ||
2270 | @var{bag}: The bag | ||
2271 | |||
2272 | @var{indx}: The element of the bag to get the type | ||
2273 | |||
2274 | This function will return the bag's type. One of the gnutls_pkcs12_bag_type_t | ||
2275 | enumerations. | ||
2276 | @end deftypefun | ||
2277 | |||
2278 | @subheading gnutls_pkcs12_bag_get_count | ||
2279 | @anchor{gnutls_pkcs12_bag_get_count} | ||
2280 | @deftypefun {int} {gnutls_pkcs12_bag_get_count} (gnutls_pkcs12_bag_t @var{bag}) | ||
2281 | @var{bag}: The bag | ||
2282 | |||
2283 | This function will return the number of the elements withing the bag. | ||
2284 | @end deftypefun | ||
2285 | |||
2286 | @subheading gnutls_pkcs12_bag_get_data | ||
2287 | @anchor{gnutls_pkcs12_bag_get_data} | ||
2288 | @deftypefun {int} {gnutls_pkcs12_bag_get_data} (gnutls_pkcs12_bag_t @var{bag}, int @var{indx}, gnutls_datum_t * @var{data}) | ||
2289 | @var{bag}: The bag | ||
2290 | |||
2291 | @var{indx}: The element of the bag to get the data from | ||
2292 | |||
2293 | @var{data}: where the bag's data will be. Should be treated as constant. | ||
2294 | |||
2295 | This function will return the bag's data. The data is a constant | ||
2296 | that is stored into the bag. Should not be accessed after the bag | ||
2297 | is deleted. | ||
2298 | |||
2299 | Returns 0 on success and a negative error code on error. | ||
2300 | @end deftypefun | ||
2301 | |||
2302 | @subheading gnutls_pkcs12_bag_set_data | ||
2303 | @anchor{gnutls_pkcs12_bag_set_data} | ||
2304 | @deftypefun {int} {gnutls_pkcs12_bag_set_data} (gnutls_pkcs12_bag_t @var{bag}, gnutls_pkcs12_bag_type_t @var{type}, const gnutls_datum_t * @var{data}) | ||
2305 | @var{bag}: The bag | ||
2306 | |||
2307 | @var{type}: The data's type | ||
2308 | |||
2309 | @var{data}: the data to be copied. | ||
2310 | |||
2311 | This function will insert the given data of the given type into the | ||
2312 | bag. | ||
2313 | |||
2314 | Returns the index of the added bag on success, or a negative | ||
2315 | value on error. | ||
2316 | @end deftypefun | ||
2317 | |||
2318 | @subheading gnutls_pkcs12_bag_set_crt | ||
2319 | @anchor{gnutls_pkcs12_bag_set_crt} | ||
2320 | @deftypefun {int} {gnutls_pkcs12_bag_set_crt} (gnutls_pkcs12_bag_t @var{bag}, gnutls_x509_crt_t @var{crt}) | ||
2321 | @var{bag}: The bag | ||
2322 | |||
2323 | @var{crt}: the certificate to be copied. | ||
2324 | |||
2325 | This function will insert the given certificate into the | ||
2326 | bag. This is just a wrapper over @code{gnutls_pkcs12_bag_set_data()}. | ||
2327 | |||
2328 | Returns the index of the added bag on success, or a negative | ||
2329 | value on failure. | ||
2330 | @end deftypefun | ||
2331 | |||
2332 | @subheading gnutls_pkcs12_bag_set_crl | ||
2333 | @anchor{gnutls_pkcs12_bag_set_crl} | ||
2334 | @deftypefun {int} {gnutls_pkcs12_bag_set_crl} (gnutls_pkcs12_bag_t @var{bag}, gnutls_x509_crl_t @var{crl}) | ||
2335 | @var{bag}: The bag | ||
2336 | |||
2337 | @var{crl}: the CRL to be copied. | ||
2338 | |||
2339 | This function will insert the given CRL into the | ||
2340 | bag. This is just a wrapper over @code{gnutls_pkcs12_bag_set_data()}. | ||
2341 | |||
2342 | Returns the index of the added bag on success, or a negative | ||
2343 | value on failure. | ||
2344 | @end deftypefun | ||
2345 | |||
2346 | @subheading gnutls_pkcs12_bag_set_key_id | ||
2347 | @anchor{gnutls_pkcs12_bag_set_key_id} | ||
2348 | @deftypefun {int} {gnutls_pkcs12_bag_set_key_id} (gnutls_pkcs12_bag_t @var{bag}, int @var{indx}, const gnutls_datum_t * @var{id}) | ||
2349 | @var{bag}: The bag | ||
2350 | |||
2351 | @var{indx}: The bag's element to add the id | ||
2352 | |||
2353 | @var{id}: the ID | ||
2354 | |||
2355 | This function will add the given key ID, to the specified, by the index, bag | ||
2356 | element. The key ID will be encoded as a 'Local key identifier' bag attribute, | ||
2357 | which is usually used to distinguish the local private key and the certificate pair. | ||
2358 | |||
2359 | Returns 0 on success, or a negative value on error. | ||
2360 | @end deftypefun | ||
2361 | |||
2362 | @subheading gnutls_pkcs12_bag_get_key_id | ||
2363 | @anchor{gnutls_pkcs12_bag_get_key_id} | ||
2364 | @deftypefun {int} {gnutls_pkcs12_bag_get_key_id} (gnutls_pkcs12_bag_t @var{bag}, int @var{indx}, gnutls_datum_t * @var{id}) | ||
2365 | @var{bag}: The bag | ||
2366 | |||
2367 | @var{indx}: The bag's element to add the id | ||
2368 | |||
2369 | @var{id}: where the ID will be copied (to be treated as const) | ||
2370 | |||
2371 | This function will return the key ID, of the specified bag element. | ||
2372 | The key ID is usually used to distinguish the local private key and the certificate pair. | ||
2373 | |||
2374 | Returns 0 on success, or a negative value on error. | ||
2375 | @end deftypefun | ||
2376 | |||
2377 | @subheading gnutls_pkcs12_bag_get_friendly_name | ||
2378 | @anchor{gnutls_pkcs12_bag_get_friendly_name} | ||
2379 | @deftypefun {int} {gnutls_pkcs12_bag_get_friendly_name} (gnutls_pkcs12_bag_t @var{bag}, int @var{indx}, char ** @var{name}) | ||
2380 | @var{bag}: The bag | ||
2381 | |||
2382 | @var{indx}: The bag's element to add the id | ||
2383 | |||
2384 | @var{name}: will hold a pointer to the name (to be treated as const) | ||
2385 | |||
2386 | This function will return the friendly name, of the specified bag element. | ||
2387 | The key ID is usually used to distinguish the local private key and the certificate pair. | ||
2388 | |||
2389 | Returns 0 on success, or a negative value on error. | ||
2390 | @end deftypefun | ||
2391 | |||
2392 | @subheading gnutls_pkcs12_bag_set_friendly_name | ||
2393 | @anchor{gnutls_pkcs12_bag_set_friendly_name} | ||
2394 | @deftypefun {int} {gnutls_pkcs12_bag_set_friendly_name} (gnutls_pkcs12_bag_t @var{bag}, int @var{indx}, const char * @var{name}) | ||
2395 | @var{bag}: The bag | ||
2396 | |||
2397 | @var{indx}: The bag's element to add the id | ||
2398 | |||
2399 | @var{name}: the name | ||
2400 | |||
2401 | This function will add the given key friendly name, to the specified, by the index, bag | ||
2402 | element. The name will be encoded as a 'Friendly name' bag attribute, | ||
2403 | which is usually used to set a user name to the local private key and the certificate pair. | ||
2404 | |||
2405 | Returns 0 on success, or a negative value on error. | ||
2406 | @end deftypefun | ||
2407 | |||
2408 | @subheading gnutls_pkcs12_bag_decrypt | ||
2409 | @anchor{gnutls_pkcs12_bag_decrypt} | ||
2410 | @deftypefun {int} {gnutls_pkcs12_bag_decrypt} (gnutls_pkcs12_bag_t @var{bag}, const char * @var{pass}) | ||
2411 | @var{bag}: The bag | ||
2412 | |||
2413 | @var{pass}: The password used for encryption. This can only be ASCII. | ||
2414 | |||
2415 | This function will decrypt the given encrypted bag and return 0 on success. | ||
2416 | @end deftypefun | ||
2417 | |||
2418 | @subheading gnutls_pkcs12_bag_encrypt | ||
2419 | @anchor{gnutls_pkcs12_bag_encrypt} | ||
2420 | @deftypefun {int} {gnutls_pkcs12_bag_encrypt} (gnutls_pkcs12_bag_t @var{bag}, const char * @var{pass}, unsigned int @var{flags}) | ||
2421 | @var{bag}: The bag | ||
2422 | |||
2423 | @var{pass}: The password used for encryption. This can only be ASCII. | ||
2424 | |||
2425 | @var{flags}: should be one of gnutls_pkcs_encrypt_flags_t elements bitwise or'd | ||
2426 | |||
2427 | This function will encrypt the given bag and return 0 on success. | ||
2428 | @end deftypefun | ||
2429 | |||
2430 | @subheading gnutls_x509_crt_set_dn_by_oid | ||
2431 | @anchor{gnutls_x509_crt_set_dn_by_oid} | ||
2432 | @deftypefun {int} {gnutls_x509_crt_set_dn_by_oid} (gnutls_x509_crt_t @var{crt}, const char * @var{oid}, unsigned int @var{raw_flag}, const void * @var{name}, unsigned int @var{sizeof_name}) | ||
2433 | @var{crt}: should contain a gnutls_x509_crt_t structure | ||
2434 | |||
2435 | @var{oid}: holds an Object Identifier in a null terminated string | ||
2436 | |||
2437 | @var{raw_flag}: must be 0, or 1 if the data are DER encoded | ||
2438 | |||
2439 | @var{name}: a pointer to the name | ||
2440 | |||
2441 | @var{sizeof_name}: holds the size of @code{name} | ||
2442 | |||
2443 | This function will set the part of the name of the Certificate subject, specified | ||
2444 | by the given OID. The input string should be ASCII or UTF-8 encoded. | ||
2445 | |||
2446 | Some helper macros with popular OIDs can be found in gnutls/x509.h | ||
2447 | With this function you can only set the known OIDs. You can test | ||
2448 | for known OIDs using @code{gnutls_x509_dn_oid_known()}. For OIDs that are | ||
2449 | not known (by gnutls) you should properly DER encode your data, and | ||
2450 | call this function with raw_flag set. | ||
2451 | |||
2452 | Returns 0 on success. | ||
2453 | @end deftypefun | ||
2454 | |||
2455 | @subheading gnutls_x509_crt_set_issuer_dn_by_oid | ||
2456 | @anchor{gnutls_x509_crt_set_issuer_dn_by_oid} | ||
2457 | @deftypefun {int} {gnutls_x509_crt_set_issuer_dn_by_oid} (gnutls_x509_crt_t @var{crt}, const char * @var{oid}, unsigned int @var{raw_flag}, const void * @var{name}, unsigned int @var{sizeof_name}) | ||
2458 | @var{crt}: should contain a gnutls_x509_crt_t structure | ||
2459 | |||
2460 | @var{oid}: holds an Object Identifier in a null terminated string | ||
2461 | |||
2462 | @var{raw_flag}: must be 0, or 1 if the data are DER encoded | ||
2463 | |||
2464 | @var{name}: a pointer to the name | ||
2465 | |||
2466 | @var{sizeof_name}: holds the size of @code{name} | ||
2467 | |||
2468 | This function will set the part of the name of the Certificate issuer, specified | ||
2469 | by the given OID. The input string should be ASCII or UTF-8 encoded. | ||
2470 | |||
2471 | Some helper macros with popular OIDs can be found in gnutls/x509.h | ||
2472 | With this function you can only set the known OIDs. You can test | ||
2473 | for known OIDs using @code{gnutls_x509_dn_oid_known()}. For OIDs that are | ||
2474 | not known (by gnutls) you should properly DER encode your data, and | ||
2475 | call this function with raw_flag set. | ||
2476 | |||
2477 | Normally you do not need to call this function, since the signing | ||
2478 | operation will copy the signer's name as the issuer of the certificate. | ||
2479 | |||
2480 | Returns 0 on success. | ||
2481 | @end deftypefun | ||
2482 | |||
2483 | @subheading gnutls_x509_crt_set_proxy_dn | ||
2484 | @anchor{gnutls_x509_crt_set_proxy_dn} | ||
2485 | @deftypefun {int} {gnutls_x509_crt_set_proxy_dn} (gnutls_x509_crt_t @var{crt}, gnutls_x509_crt_t @var{eecrt}, unsigned int @var{raw_flag}, const void * @var{name}, unsigned int @var{sizeof_name}) | ||
2486 | @var{crt}: a gnutls_x509_crt_t structure with the new proxy cert | ||
2487 | |||
2488 | @var{eecrt}: the end entity certificate that will be issuing the proxy | ||
2489 | |||
2490 | @var{raw_flag}: must be 0, or 1 if the CN is DER encoded | ||
2491 | |||
2492 | @var{name}: a pointer to the CN name, may be NULL (but MUST then be added later) | ||
2493 | |||
2494 | @var{sizeof_name}: holds the size of @code{name} | ||
2495 | |||
2496 | This function will set the subject in @code{crt} to the end entity's | ||
2497 | @code{eecrt} subject name, and add a single Common Name component @code{name} | ||
2498 | of size @code{sizeof_name}. This corresponds to the required proxy | ||
2499 | certificate naming style. Note that if @code{name} is @code{NULL}, you MUST | ||
2500 | set it later by using @code{gnutls_x509_crt_set_dn_by_oid()} or similar. | ||
2501 | |||
2502 | Returns 0 on success. | ||
2503 | @end deftypefun | ||
2504 | |||
2505 | @subheading gnutls_x509_crt_set_version | ||
2506 | @anchor{gnutls_x509_crt_set_version} | ||
2507 | @deftypefun {int} {gnutls_x509_crt_set_version} (gnutls_x509_crt_t @var{crt}, unsigned int @var{version}) | ||
2508 | @var{crt}: should contain a gnutls_x509_crt_t structure | ||
2509 | |||
2510 | @var{version}: holds the version number. For X.509v1 certificates must be 1. | ||
2511 | |||
2512 | This function will set the version of the certificate. This must | ||
2513 | be one for X.509 version 1, and so on. Plain certificates without | ||
2514 | extensions must have version set to one. | ||
2515 | |||
2516 | To create well-formed certificates, you must specify version 3 if | ||
2517 | you use any certificate extensions. Extensions are created by | ||
2518 | functions such as gnutls_x509_crt_set_subject_alternative_name or | ||
2519 | gnutls_x509_crt_set_key_usage. | ||
2520 | |||
2521 | Returns 0 on success. | ||
2522 | @end deftypefun | ||
2523 | |||
2524 | @subheading gnutls_x509_crt_set_key | ||
2525 | @anchor{gnutls_x509_crt_set_key} | ||
2526 | @deftypefun {int} {gnutls_x509_crt_set_key} (gnutls_x509_crt_t @var{crt}, gnutls_x509_privkey_t @var{key}) | ||
2527 | @var{crt}: should contain a gnutls_x509_crt_t structure | ||
2528 | |||
2529 | @var{key}: holds a private key | ||
2530 | |||
2531 | This function will set the public parameters from the given private key to the | ||
2532 | certificate. Only RSA keys are currently supported. | ||
2533 | |||
2534 | Returns 0 on success. | ||
2535 | @end deftypefun | ||
2536 | |||
2537 | @subheading gnutls_x509_crt_set_crq | ||
2538 | @anchor{gnutls_x509_crt_set_crq} | ||
2539 | @deftypefun {int} {gnutls_x509_crt_set_crq} (gnutls_x509_crt_t @var{crt}, gnutls_x509_crq_t @var{crq}) | ||
2540 | @var{crt}: should contain a gnutls_x509_crt_t structure | ||
2541 | |||
2542 | @var{crq}: holds a certificate request | ||
2543 | |||
2544 | This function will set the name and public parameters from the given certificate request to the | ||
2545 | certificate. Only RSA keys are currently supported. | ||
2546 | |||
2547 | Returns 0 on success. | ||
2548 | @end deftypefun | ||
2549 | |||
2550 | @subheading gnutls_x509_crt_set_extension_by_oid | ||
2551 | @anchor{gnutls_x509_crt_set_extension_by_oid} | ||
2552 | @deftypefun {int} {gnutls_x509_crt_set_extension_by_oid} (gnutls_x509_crt_t @var{crt}, const char * @var{oid}, const void * @var{buf}, size_t @var{sizeof_buf}, unsigned int @var{critical}) | ||
2553 | @var{crt}: should contain a gnutls_x509_crt_t structure | ||
2554 | |||
2555 | @var{oid}: holds an Object Identified in null terminated string | ||
2556 | |||
2557 | @var{buf}: a pointer to a DER encoded data | ||
2558 | |||
2559 | @var{sizeof_buf}: holds the size of @code{buf} | ||
2560 | |||
2561 | @var{critical}: should be non zero if the extension is to be marked as critical | ||
2562 | |||
2563 | This function will set an the extension, by the specified OID, in the certificate. | ||
2564 | The extension data should be binary data DER encoded. | ||
2565 | |||
2566 | Returns 0 on success and a negative value in case of an error. | ||
2567 | @end deftypefun | ||
2568 | |||
2569 | @subheading gnutls_x509_crt_set_basic_constraints | ||
2570 | @anchor{gnutls_x509_crt_set_basic_constraints} | ||
2571 | @deftypefun {int} {gnutls_x509_crt_set_basic_constraints} (gnutls_x509_crt_t @var{crt}, unsigned int @var{ca}, int @var{pathLenConstraint}) | ||
2572 | @var{crt}: should contain a gnutls_x509_crt_t structure | ||
2573 | |||
2574 | @var{ca}: true(1) or false(0). Depending on the Certificate authority status. | ||
2575 | |||
2576 | @var{pathLenConstraint}: non-negative values indicate maximum length of path, | ||
2577 | and negative values indicate that the pathLenConstraints field should | ||
2578 | not be present. | ||
2579 | |||
2580 | This function will set the basicConstraints certificate extension. | ||
2581 | |||
2582 | Returns 0 on success. | ||
2583 | @end deftypefun | ||
2584 | |||
2585 | @subheading gnutls_x509_crt_set_ca_status | ||
2586 | @anchor{gnutls_x509_crt_set_ca_status} | ||
2587 | @deftypefun {int} {gnutls_x509_crt_set_ca_status} (gnutls_x509_crt_t @var{crt}, unsigned int @var{ca}) | ||
2588 | @var{crt}: should contain a gnutls_x509_crt_t structure | ||
2589 | |||
2590 | @var{ca}: true(1) or false(0). Depending on the Certificate authority status. | ||
2591 | |||
2592 | This function will set the basicConstraints certificate extension. | ||
2593 | Use @code{gnutls_x509_crt_set_basic_constraints()} if you want to control | ||
2594 | the pathLenConstraint field too. | ||
2595 | |||
2596 | Returns 0 on success. | ||
2597 | @end deftypefun | ||
2598 | |||
2599 | @subheading gnutls_x509_crt_set_key_usage | ||
2600 | @anchor{gnutls_x509_crt_set_key_usage} | ||
2601 | @deftypefun {int} {gnutls_x509_crt_set_key_usage} (gnutls_x509_crt_t @var{crt}, unsigned int @var{usage}) | ||
2602 | @var{crt}: should contain a gnutls_x509_crt_t structure | ||
2603 | |||
2604 | @var{usage}: an ORed sequence of the GNUTLS_KEY_* elements. | ||
2605 | |||
2606 | This function will set the keyUsage certificate extension. | ||
2607 | |||
2608 | Returns 0 on success. | ||
2609 | @end deftypefun | ||
2610 | |||
2611 | @subheading gnutls_x509_crt_set_subject_alternative_name | ||
2612 | @anchor{gnutls_x509_crt_set_subject_alternative_name} | ||
2613 | @deftypefun {int} {gnutls_x509_crt_set_subject_alternative_name} (gnutls_x509_crt_t @var{crt}, gnutls_x509_subject_alt_name_t @var{type}, const char * @var{data_string}) | ||
2614 | @var{crt}: should contain a gnutls_x509_crt_t structure | ||
2615 | |||
2616 | @var{type}: is one of the gnutls_x509_subject_alt_name_t enumerations | ||
2617 | |||
2618 | @var{data_string}: The data to be set | ||
2619 | |||
2620 | This function will set the subject alternative name certificate extension. | ||
2621 | |||
2622 | Returns 0 on success. | ||
2623 | @end deftypefun | ||
2624 | |||
2625 | @subheading gnutls_x509_crt_set_proxy | ||
2626 | @anchor{gnutls_x509_crt_set_proxy} | ||
2627 | @deftypefun {int} {gnutls_x509_crt_set_proxy} (gnutls_x509_crt_t @var{crt}, int @var{pathLenConstraint}, const char * @var{policyLanguage}, const char * @var{policy}, size_t @var{sizeof_policy}) | ||
2628 | @var{crt}: should contain a gnutls_x509_crt_t structure | ||
2629 | |||
2630 | @var{pathLenConstraint}: non-negative values indicate maximum length of path, | ||
2631 | and negative values indicate that the pathLenConstraints field should | ||
2632 | not be present. | ||
2633 | |||
2634 | @var{policyLanguage}: OID describing the language of @code{policy}. | ||
2635 | |||
2636 | @var{policy}: opaque byte array with policy language, can be @code{NULL} | ||
2637 | |||
2638 | @var{sizeof_policy}: size of @code{policy}. | ||
2639 | |||
2640 | This function will set the proxyCertInfo extension. | ||
2641 | |||
2642 | Returns 0 on success. | ||
2643 | @end deftypefun | ||
2644 | |||
2645 | @subheading gnutls_x509_crt_sign2 | ||
2646 | @anchor{gnutls_x509_crt_sign2} | ||
2647 | @deftypefun {int} {gnutls_x509_crt_sign2} (gnutls_x509_crt_t @var{crt}, gnutls_x509_crt_t @var{issuer}, gnutls_x509_privkey_t @var{issuer_key}, gnutls_digest_algorithm_t @var{dig}, unsigned int @var{flags}) | ||
2648 | @var{crt}: should contain a gnutls_x509_crt_t structure | ||
2649 | |||
2650 | @var{issuer}: is the certificate of the certificate issuer | ||
2651 | |||
2652 | @var{issuer_key}: holds the issuer's private key | ||
2653 | |||
2654 | @var{dig}: The message digest to use. GNUTLS_DIG_SHA1 is the safe choice unless you know what you're doing. | ||
2655 | |||
2656 | @var{flags}: must be 0 | ||
2657 | |||
2658 | This function will sign the certificate with the issuer's private key, and | ||
2659 | will copy the issuer's information into the certificate. | ||
2660 | |||
2661 | This must be the last step in a certificate generation since all | ||
2662 | the previously set parameters are now signed. | ||
2663 | |||
2664 | Returns 0 on success. | ||
2665 | @end deftypefun | ||
2666 | |||
2667 | @subheading gnutls_x509_crt_sign | ||
2668 | @anchor{gnutls_x509_crt_sign} | ||
2669 | @deftypefun {int} {gnutls_x509_crt_sign} (gnutls_x509_crt_t @var{crt}, gnutls_x509_crt_t @var{issuer}, gnutls_x509_privkey_t @var{issuer_key}) | ||
2670 | @var{crt}: should contain a gnutls_x509_crt_t structure | ||
2671 | |||
2672 | @var{issuer}: is the certificate of the certificate issuer | ||
2673 | |||
2674 | @var{issuer_key}: holds the issuer's private key | ||
2675 | |||
2676 | This function is the same a @code{gnutls_x509_crt_sign2()} with no flags, and | ||
2677 | SHA1 as the hash algorithm. | ||
2678 | |||
2679 | Returns 0 on success. | ||
2680 | @end deftypefun | ||
2681 | |||
2682 | @subheading gnutls_x509_crt_set_activation_time | ||
2683 | @anchor{gnutls_x509_crt_set_activation_time} | ||
2684 | @deftypefun {int} {gnutls_x509_crt_set_activation_time} (gnutls_x509_crt_t @var{cert}, time_t @var{act_time}) | ||
2685 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
2686 | |||
2687 | @var{act_time}: The actual time | ||
2688 | |||
2689 | This function will set the time this Certificate was or will be activated. | ||
2690 | |||
2691 | Returns 0 on success, or a negative value in case of an error. | ||
2692 | @end deftypefun | ||
2693 | |||
2694 | @subheading gnutls_x509_crt_set_expiration_time | ||
2695 | @anchor{gnutls_x509_crt_set_expiration_time} | ||
2696 | @deftypefun {int} {gnutls_x509_crt_set_expiration_time} (gnutls_x509_crt_t @var{cert}, time_t @var{exp_time}) | ||
2697 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
2698 | |||
2699 | @var{exp_time}: The actual time | ||
2700 | |||
2701 | This function will set the time this Certificate will expire. | ||
2702 | |||
2703 | Returns 0 on success, or a negative value in case of an error. | ||
2704 | @end deftypefun | ||
2705 | |||
2706 | @subheading gnutls_x509_crt_set_serial | ||
2707 | @anchor{gnutls_x509_crt_set_serial} | ||
2708 | @deftypefun {int} {gnutls_x509_crt_set_serial} (gnutls_x509_crt_t @var{cert}, const void * @var{serial}, size_t @var{serial_size}) | ||
2709 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
2710 | |||
2711 | @var{serial}: The serial number | ||
2712 | |||
2713 | @var{serial_size}: Holds the size of the serial field. | ||
2714 | |||
2715 | This function will set the X.509 certificate's serial number. | ||
2716 | Serial is not always a 32 or 64bit number. Some CAs use | ||
2717 | large serial numbers, thus it may be wise to handle it as something | ||
2718 | opaque. | ||
2719 | |||
2720 | Returns 0 on success, or a negative value in case of an error. | ||
2721 | @end deftypefun | ||
2722 | |||
2723 | @subheading gnutls_x509_crt_set_crl_dist_points | ||
2724 | @anchor{gnutls_x509_crt_set_crl_dist_points} | ||
2725 | @deftypefun {int} {gnutls_x509_crt_set_crl_dist_points} (gnutls_x509_crt_t @var{crt}, gnutls_x509_subject_alt_name_t @var{type}, const void * @var{data_string}, unsigned int @var{reason_flags}) | ||
2726 | @var{crt}: should contain a gnutls_x509_crt_t structure | ||
2727 | |||
2728 | @var{type}: is one of the gnutls_x509_subject_alt_name_t enumerations | ||
2729 | |||
2730 | @var{data_string}: The data to be set | ||
2731 | |||
2732 | @var{reason_flags}: revocation reasons | ||
2733 | |||
2734 | This function will set the CRL distribution points certificate extension. | ||
2735 | |||
2736 | Returns 0 on success. | ||
2737 | @end deftypefun | ||
2738 | |||
2739 | @subheading gnutls_x509_crt_cpy_crl_dist_points | ||
2740 | @anchor{gnutls_x509_crt_cpy_crl_dist_points} | ||
2741 | @deftypefun {int} {gnutls_x509_crt_cpy_crl_dist_points} (gnutls_x509_crt_t @var{dst}, gnutls_x509_crt_t @var{src}) | ||
2742 | @var{dst}: should contain a gnutls_x509_crt_t structure | ||
2743 | |||
2744 | @var{src}: the certificate where the dist points will be copied from | ||
2745 | |||
2746 | This function will copy the CRL distribution points certificate | ||
2747 | extension, from the source to the destination certificate. | ||
2748 | This may be useful to copy from a CA certificate to issued ones. | ||
2749 | |||
2750 | Returns 0 on success. | ||
2751 | @end deftypefun | ||
2752 | |||
2753 | @subheading gnutls_x509_crt_set_subject_key_id | ||
2754 | @anchor{gnutls_x509_crt_set_subject_key_id} | ||
2755 | @deftypefun {int} {gnutls_x509_crt_set_subject_key_id} (gnutls_x509_crt_t @var{cert}, const void * @var{id}, size_t @var{id_size}) | ||
2756 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
2757 | |||
2758 | @var{id}: The key ID | ||
2759 | |||
2760 | @var{id_size}: Holds the size of the serial field. | ||
2761 | |||
2762 | This function will set the X.509 certificate's subject key ID extension. | ||
2763 | |||
2764 | Returns 0 on success, or a negative value in case of an error. | ||
2765 | @end deftypefun | ||
2766 | |||
2767 | @subheading gnutls_x509_crt_set_authority_key_id | ||
2768 | @anchor{gnutls_x509_crt_set_authority_key_id} | ||
2769 | @deftypefun {int} {gnutls_x509_crt_set_authority_key_id} (gnutls_x509_crt_t @var{cert}, const void * @var{id}, size_t @var{id_size}) | ||
2770 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
2771 | |||
2772 | @var{id}: The key ID | ||
2773 | |||
2774 | @var{id_size}: Holds the size of the serial field. | ||
2775 | |||
2776 | This function will set the X.509 certificate's authority key ID extension. | ||
2777 | Only the keyIdentifier field can be set with this function. | ||
2778 | |||
2779 | Returns 0 on success, or a negative value in case of an error. | ||
2780 | @end deftypefun | ||
2781 | |||
2782 | @subheading gnutls_x509_crt_set_key_purpose_oid | ||
2783 | @anchor{gnutls_x509_crt_set_key_purpose_oid} | ||
2784 | @deftypefun {int} {gnutls_x509_crt_set_key_purpose_oid} (gnutls_x509_crt_t @var{cert}, const void * @var{oid}, unsigned int @var{critical}) | ||
2785 | @var{cert}: should contain a gnutls_x509_crt_t structure | ||
2786 | |||
2787 | @var{oid}: a pointer to a null terminated string that holds the OID | ||
2788 | |||
2789 | @var{critical}: Whether this extension will be critical or not | ||
2790 | |||
2791 | This function will set the key purpose OIDs of the Certificate. | ||
2792 | These are stored in the Extended Key Usage extension (2.5.29.37) | ||
2793 | See the GNUTLS_KP_* definitions for human readable names. | ||
2794 | |||
2795 | Subsequent calls to this function will append OIDs to the OID list. | ||
2796 | |||
2797 | On success 0 is returned. | ||
2798 | @end deftypefun | ||
2799 | |||
2800 | @subheading gnutls_x509_crl_set_version | ||
2801 | @anchor{gnutls_x509_crl_set_version} | ||
2802 | @deftypefun {int} {gnutls_x509_crl_set_version} (gnutls_x509_crl_t @var{crl}, unsigned int @var{version}) | ||
2803 | @var{crl}: should contain a gnutls_x509_crl_t structure | ||
2804 | |||
2805 | @var{version}: holds the version number. For CRLv1 crls must be 1. | ||
2806 | |||
2807 | This function will set the version of the CRL. This | ||
2808 | must be one for CRL version 1, and so on. The CRLs generated | ||
2809 | by gnutls should have a version number of 2. | ||
2810 | |||
2811 | Returns 0 on success. | ||
2812 | @end deftypefun | ||
2813 | |||
2814 | @subheading gnutls_x509_crl_sign2 | ||
2815 | @anchor{gnutls_x509_crl_sign2} | ||
2816 | @deftypefun {int} {gnutls_x509_crl_sign2} (gnutls_x509_crl_t @var{crl}, gnutls_x509_crt_t @var{issuer}, gnutls_x509_privkey_t @var{issuer_key}, gnutls_digest_algorithm_t @var{dig}, unsigned int @var{flags}) | ||
2817 | @var{crl}: should contain a gnutls_x509_crl_t structure | ||
2818 | |||
2819 | @var{issuer}: is the certificate of the certificate issuer | ||
2820 | |||
2821 | @var{issuer_key}: holds the issuer's private key | ||
2822 | |||
2823 | @var{dig}: The message digest to use. GNUTLS_DIG_SHA1 is the safe choice unless you know what you're doing. | ||
2824 | |||
2825 | @var{flags}: must be 0 | ||
2826 | |||
2827 | This function will sign the CRL with the issuer's private key, and | ||
2828 | will copy the issuer's information into the CRL. | ||
2829 | |||
2830 | This must be the last step in a certificate CRL since all | ||
2831 | the previously set parameters are now signed. | ||
2832 | |||
2833 | Returns 0 on success. | ||
2834 | @end deftypefun | ||
2835 | |||
2836 | @subheading gnutls_x509_crl_sign | ||
2837 | @anchor{gnutls_x509_crl_sign} | ||
2838 | @deftypefun {int} {gnutls_x509_crl_sign} (gnutls_x509_crl_t @var{crl}, gnutls_x509_crt_t @var{issuer}, gnutls_x509_privkey_t @var{issuer_key}) | ||
2839 | @var{crl}: should contain a gnutls_x509_crl_t structure | ||
2840 | |||
2841 | @var{issuer}: is the certificate of the certificate issuer | ||
2842 | |||
2843 | @var{issuer_key}: holds the issuer's private key | ||
2844 | |||
2845 | This function is the same a @code{gnutls_x509_crl_sign2()} with no flags, and | ||
2846 | SHA1 as the hash algorithm. | ||
2847 | |||
2848 | Returns 0 on success. | ||
2849 | @end deftypefun | ||
2850 | |||
2851 | @subheading gnutls_x509_crl_set_this_update | ||
2852 | @anchor{gnutls_x509_crl_set_this_update} | ||
2853 | @deftypefun {int} {gnutls_x509_crl_set_this_update} (gnutls_x509_crl_t @var{crl}, time_t @var{act_time}) | ||
2854 | @var{crl}: should contain a gnutls_x509_crl_t structure | ||
2855 | |||
2856 | @var{act_time}: The actual time | ||
2857 | |||
2858 | This function will set the time this CRL was issued. | ||
2859 | |||
2860 | Returns 0 on success, or a negative value in case of an error. | ||
2861 | @end deftypefun | ||
2862 | |||
2863 | @subheading gnutls_x509_crl_set_next_update | ||
2864 | @anchor{gnutls_x509_crl_set_next_update} | ||
2865 | @deftypefun {int} {gnutls_x509_crl_set_next_update} (gnutls_x509_crl_t @var{crl}, time_t @var{exp_time}) | ||
2866 | @var{crl}: should contain a gnutls_x509_crl_t structure | ||
2867 | |||
2868 | @var{exp_time}: The actual time | ||
2869 | |||
2870 | This function will set the time this CRL will be updated. | ||
2871 | |||
2872 | Returns 0 on success, or a negative value in case of an error. | ||
2873 | @end deftypefun | ||
2874 | |||
2875 | @subheading gnutls_x509_crl_set_crt_serial | ||
2876 | @anchor{gnutls_x509_crl_set_crt_serial} | ||
2877 | @deftypefun {int} {gnutls_x509_crl_set_crt_serial} (gnutls_x509_crl_t @var{crl}, const void * @var{serial}, size_t @var{serial_size}, time_t @var{revocation_time}) | ||
2878 | @var{crl}: should contain a gnutls_x509_crl_t structure | ||
2879 | |||
2880 | @var{serial}: The revoked certificate's serial number | ||
2881 | |||
2882 | @var{serial_size}: Holds the size of the serial field. | ||
2883 | |||
2884 | @var{revocation_time}: The time this certificate was revoked | ||
2885 | |||
2886 | This function will set a revoked certificate's serial number to the CRL. | ||
2887 | |||
2888 | Returns 0 on success, or a negative value in case of an error. | ||
2889 | @end deftypefun | ||
2890 | |||
2891 | @subheading gnutls_x509_crl_set_crt | ||
2892 | @anchor{gnutls_x509_crl_set_crt} | ||
2893 | @deftypefun {int} {gnutls_x509_crl_set_crt} (gnutls_x509_crl_t @var{crl}, gnutls_x509_crt_t @var{crt}, time_t @var{revocation_time}) | ||
2894 | @var{crl}: should contain a gnutls_x509_crl_t structure | ||
2895 | |||
2896 | @var{crt}: should contain a gnutls_x509_crt_t structure with the revoked certificate | ||
2897 | |||
2898 | @var{revocation_time}: The time this certificate was revoked | ||
2899 | |||
2900 | This function will set a revoked certificate's serial number to the CRL. | ||
2901 | |||
2902 | Returns 0 on success, or a negative value in case of an error. | ||
2903 | @end deftypefun | ||
2904 | |||
2905 | @subheading gnutls_x509_crt_print | ||
2906 | @anchor{gnutls_x509_crt_print} | ||
2907 | @deftypefun {int} {gnutls_x509_crt_print} (gnutls_x509_crt_t @var{cert}, gnutls_certificate_print_formats_t @var{format}, gnutls_datum_t * @var{out}) | ||
2908 | @var{cert}: The structure to be printed | ||
2909 | |||
2910 | @var{format}: Indicate the format to use | ||
2911 | |||
2912 | @var{out}: Newly allocated datum with zero terminated string. | ||
2913 | |||
2914 | This function will pretty print a X.509 certificate, suitable for | ||
2915 | display to a human. | ||
2916 | |||
2917 | If the format is @code{GNUTLS_X509_CRT_FULL} then all fields of the | ||
2918 | certificate will be output, on multiple lines. The | ||
2919 | @code{GNUTLS_X509_CRT_ONELINE} format will generate one line with some | ||
2920 | selected fields, which is useful for logging purposes. | ||
2921 | |||
2922 | The output @code{out} needs to be deallocate using @code{gnutls_free()}. | ||
2923 | |||
2924 | Returns 0 on success. | ||
2925 | @end deftypefun | ||
2926 | |||
2927 | @subheading gnutls_x509_crl_print | ||
2928 | @anchor{gnutls_x509_crl_print} | ||
2929 | @deftypefun {int} {gnutls_x509_crl_print} (gnutls_x509_crl_t @var{crl}, gnutls_certificate_print_formats_t @var{format}, gnutls_datum_t * @var{out}) | ||
2930 | @var{crl}: The structure to be printed | ||
2931 | |||
2932 | @var{format}: Indicate the format to use | ||
2933 | |||
2934 | @var{out}: Newly allocated datum with zero terminated string. | ||
2935 | |||
2936 | This function will pretty print a X.509 certificate revocation | ||
2937 | list, suitable for display to a human. | ||
2938 | |||
2939 | The output @code{out} needs to be deallocate using @code{gnutls_free()}. | ||
2940 | |||
2941 | Returns 0 on success. | ||
2942 | @end deftypefun | ||
2943 | |||
diff --git a/src/daemon/https/x509/x509.c b/src/daemon/https/x509/x509.c new file mode 100644 index 00000000..96999d27 --- /dev/null +++ b/src/daemon/https/x509/x509.c | |||
@@ -0,0 +1,2851 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation | ||
3 | * Author: Nikos Mavrogiannopoulos, Simon Josefsson, Howard Chu | ||
4 | * | ||
5 | * This file is part of GNUTLS. | ||
6 | * | ||
7 | * The GNUTLS library is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU Lesser General Public License | ||
9 | * as published by the Free Software Foundation; either version 2.1 of | ||
10 | * the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This library is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public | ||
18 | * License along with this library; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
20 | * USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | /* Functions on X.509 Certificate parsing | ||
25 | */ | ||
26 | |||
27 | #include <gnutls_int.h> | ||
28 | #include <gnutls_datum.h> | ||
29 | #include <gnutls_global.h> | ||
30 | #include <gnutls_errors.h> | ||
31 | #include <common.h> | ||
32 | #include <gnutls_x509.h> | ||
33 | #include <x509_b64.h> | ||
34 | #include <x509.h> | ||
35 | #include <dn.h> | ||
36 | #include <extensions.h> | ||
37 | #include <libtasn1.h> | ||
38 | #include <mpi.h> | ||
39 | #include <privkey.h> | ||
40 | #include <verify.h> | ||
41 | |||
42 | /** | ||
43 | * gnutls_x509_crt_init - This function initializes a gnutls_x509_crt_t structure | ||
44 | * @cert: The structure to be initialized | ||
45 | * | ||
46 | * This function will initialize an X.509 certificate structure. | ||
47 | * | ||
48 | * Returns 0 on success. | ||
49 | * | ||
50 | **/ | ||
51 | int | ||
52 | gnutls_x509_crt_init (gnutls_x509_crt_t * cert) | ||
53 | { | ||
54 | gnutls_x509_crt_t tmp = gnutls_calloc (1, sizeof (gnutls_x509_crt_int)); | ||
55 | int result; | ||
56 | |||
57 | if (!tmp) | ||
58 | return GNUTLS_E_MEMORY_ERROR; | ||
59 | |||
60 | result = asn1_create_element (_gnutls_get_pkix (), | ||
61 | "PKIX1.Certificate", &tmp->cert); | ||
62 | if (result != ASN1_SUCCESS) | ||
63 | { | ||
64 | gnutls_assert (); | ||
65 | gnutls_free (tmp); | ||
66 | return _gnutls_asn2err (result); | ||
67 | } | ||
68 | |||
69 | *cert = tmp; | ||
70 | |||
71 | return 0; /* success */ | ||
72 | } | ||
73 | |||
74 | /*- | ||
75 | * _gnutls_x509_crt_cpy - This function copies a gnutls_x509_crt_t structure | ||
76 | * @dest: The structure where to copy | ||
77 | * @src: The structure to be copied | ||
78 | * | ||
79 | * This function will copy an X.509 certificate structure. | ||
80 | * | ||
81 | * Returns 0 on success. | ||
82 | * | ||
83 | -*/ | ||
84 | int | ||
85 | _gnutls_x509_crt_cpy (gnutls_x509_crt_t dest, gnutls_x509_crt_t src) | ||
86 | { | ||
87 | int ret; | ||
88 | size_t der_size; | ||
89 | opaque *der; | ||
90 | gnutls_datum_t tmp; | ||
91 | |||
92 | ret = gnutls_x509_crt_export (src, GNUTLS_X509_FMT_DER, NULL, &der_size); | ||
93 | if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) | ||
94 | { | ||
95 | gnutls_assert (); | ||
96 | return ret; | ||
97 | } | ||
98 | |||
99 | der = gnutls_alloca (der_size); | ||
100 | if (der == NULL) | ||
101 | { | ||
102 | gnutls_assert (); | ||
103 | return GNUTLS_E_MEMORY_ERROR; | ||
104 | } | ||
105 | |||
106 | ret = gnutls_x509_crt_export (src, GNUTLS_X509_FMT_DER, der, &der_size); | ||
107 | if (ret < 0) | ||
108 | { | ||
109 | gnutls_assert (); | ||
110 | gnutls_afree (der); | ||
111 | return ret; | ||
112 | } | ||
113 | |||
114 | tmp.data = der; | ||
115 | tmp.size = der_size; | ||
116 | ret = gnutls_x509_crt_import (dest, &tmp, GNUTLS_X509_FMT_DER); | ||
117 | |||
118 | gnutls_afree (der); | ||
119 | |||
120 | if (ret < 0) | ||
121 | { | ||
122 | gnutls_assert (); | ||
123 | return ret; | ||
124 | } | ||
125 | |||
126 | return 0; | ||
127 | |||
128 | } | ||
129 | |||
130 | /** | ||
131 | * gnutls_x509_crt_deinit - This function deinitializes memory used by a gnutls_x509_crt_t structure | ||
132 | * @cert: The structure to be initialized | ||
133 | * | ||
134 | * This function will deinitialize a CRL structure. | ||
135 | * | ||
136 | **/ | ||
137 | void | ||
138 | gnutls_x509_crt_deinit (gnutls_x509_crt_t cert) | ||
139 | { | ||
140 | if (!cert) | ||
141 | return; | ||
142 | |||
143 | if (cert->cert) | ||
144 | asn1_delete_structure (&cert->cert); | ||
145 | |||
146 | gnutls_free (cert); | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * gnutls_x509_crt_import - This function will import a DER or PEM encoded Certificate | ||
151 | * @cert: The structure to store the parsed certificate. | ||
152 | * @data: The DER or PEM encoded certificate. | ||
153 | * @format: One of DER or PEM | ||
154 | * | ||
155 | * This function will convert the given DER or PEM encoded Certificate | ||
156 | * to the native gnutls_x509_crt_t format. The output will be stored in @cert. | ||
157 | * | ||
158 | * If the Certificate is PEM encoded it should have a header of "X509 CERTIFICATE", or | ||
159 | * "CERTIFICATE". | ||
160 | * | ||
161 | * Returns 0 on success. | ||
162 | * | ||
163 | **/ | ||
164 | int | ||
165 | gnutls_x509_crt_import (gnutls_x509_crt_t cert, | ||
166 | const gnutls_datum_t * data, | ||
167 | gnutls_x509_crt_fmt_t format) | ||
168 | { | ||
169 | int result = 0, need_free = 0; | ||
170 | gnutls_datum_t _data; | ||
171 | opaque *signature = NULL; | ||
172 | |||
173 | if (cert == NULL) | ||
174 | { | ||
175 | gnutls_assert (); | ||
176 | return GNUTLS_E_INVALID_REQUEST; | ||
177 | } | ||
178 | |||
179 | _data.data = data->data; | ||
180 | _data.size = data->size; | ||
181 | |||
182 | /* If the Certificate is in PEM format then decode it | ||
183 | */ | ||
184 | if (format == GNUTLS_X509_FMT_PEM) | ||
185 | { | ||
186 | opaque *out; | ||
187 | |||
188 | /* Try the first header */ | ||
189 | result = _gnutls_fbase64_decode (PEM_X509_CERT2, data->data, data->size, | ||
190 | &out); | ||
191 | |||
192 | if (result <= 0) | ||
193 | { | ||
194 | /* try for the second header */ | ||
195 | result = _gnutls_fbase64_decode (PEM_X509_CERT, data->data, | ||
196 | data->size, &out); | ||
197 | |||
198 | if (result <= 0) | ||
199 | { | ||
200 | if (result == 0) | ||
201 | result = GNUTLS_E_INTERNAL_ERROR; | ||
202 | gnutls_assert (); | ||
203 | return result; | ||
204 | } | ||
205 | } | ||
206 | |||
207 | _data.data = out; | ||
208 | _data.size = result; | ||
209 | |||
210 | need_free = 1; | ||
211 | } | ||
212 | |||
213 | result = asn1_der_decoding (&cert->cert, _data.data, _data.size, NULL); | ||
214 | if (result != ASN1_SUCCESS) | ||
215 | { | ||
216 | result = _gnutls_asn2err (result); | ||
217 | gnutls_assert (); | ||
218 | goto cleanup; | ||
219 | } | ||
220 | |||
221 | /* Since we do not want to disable any extension | ||
222 | */ | ||
223 | cert->use_extensions = 1; | ||
224 | if (need_free) | ||
225 | _gnutls_free_datum (&_data); | ||
226 | |||
227 | return 0; | ||
228 | |||
229 | cleanup:gnutls_free (signature); | ||
230 | if (need_free) | ||
231 | _gnutls_free_datum (&_data); | ||
232 | return result; | ||
233 | } | ||
234 | |||
235 | /** | ||
236 | * gnutls_x509_crt_get_issuer_dn - This function returns the Certificate's issuer distinguished name | ||
237 | * @cert: should contain a gnutls_x509_crt_t structure | ||
238 | * @buf: a pointer to a structure to hold the name (may be null) | ||
239 | * @sizeof_buf: initially holds the size of @buf | ||
240 | * | ||
241 | * This function will copy the name of the Certificate issuer in the | ||
242 | * provided buffer. The name will be in the form | ||
243 | * "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253. The output string | ||
244 | * will be ASCII or UTF-8 encoded, depending on the certificate data. | ||
245 | * | ||
246 | * If @buf is null then only the size will be filled. | ||
247 | * | ||
248 | * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not | ||
249 | * long enough, and in that case the *sizeof_buf will be updated with | ||
250 | * the required size. On success 0 is returned. | ||
251 | * | ||
252 | **/ | ||
253 | int | ||
254 | gnutls_x509_crt_get_issuer_dn (gnutls_x509_crt_t cert, | ||
255 | char *buf, size_t * sizeof_buf) | ||
256 | { | ||
257 | if (cert == NULL) | ||
258 | { | ||
259 | gnutls_assert (); | ||
260 | return GNUTLS_E_INVALID_REQUEST; | ||
261 | } | ||
262 | |||
263 | return _gnutls_x509_parse_dn (cert->cert, | ||
264 | "tbsCertificate.issuer.rdnSequence", buf, | ||
265 | sizeof_buf); | ||
266 | } | ||
267 | |||
268 | /** | ||
269 | * gnutls_x509_crt_get_issuer_dn_by_oid - This function returns the Certificate's issuer distinguished name | ||
270 | * @cert: should contain a gnutls_x509_crt_t structure | ||
271 | * @oid: holds an Object Identified in null terminated string | ||
272 | * @indx: In case multiple same OIDs exist in the RDN, this specifies which to send. Use zero to get the first one. | ||
273 | * @raw_flag: If non zero returns the raw DER data of the DN part. | ||
274 | * @buf: a pointer to a structure to hold the name (may be null) | ||
275 | * @sizeof_buf: initially holds the size of @buf | ||
276 | * | ||
277 | * This function will extract the part of the name of the Certificate | ||
278 | * issuer specified by the given OID. The output, if the raw flag is not | ||
279 | * used, will be encoded as described in RFC2253. Thus a string that is | ||
280 | * ASCII or UTF-8 encoded, depending on the certificate data. | ||
281 | * | ||
282 | * Some helper macros with popular OIDs can be found in gnutls/x509.h | ||
283 | * If raw flag is zero, this function will only return known OIDs as | ||
284 | * text. Other OIDs will be DER encoded, as described in RFC2253 -- | ||
285 | * in hex format with a '\#' prefix. You can check about known OIDs | ||
286 | * using gnutls_x509_dn_oid_known(). | ||
287 | * | ||
288 | * If @buf is null then only the size will be filled. | ||
289 | * | ||
290 | * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not | ||
291 | * long enough, and in that case the *sizeof_buf will be updated with | ||
292 | * the required size. On success 0 is returned. | ||
293 | * | ||
294 | **/ | ||
295 | int | ||
296 | gnutls_x509_crt_get_issuer_dn_by_oid (gnutls_x509_crt_t cert, | ||
297 | const char *oid, | ||
298 | int indx, | ||
299 | unsigned int raw_flag, | ||
300 | void *buf, size_t * sizeof_buf) | ||
301 | { | ||
302 | if (cert == NULL) | ||
303 | { | ||
304 | gnutls_assert (); | ||
305 | return GNUTLS_E_INVALID_REQUEST; | ||
306 | } | ||
307 | |||
308 | return _gnutls_x509_parse_dn_oid (cert->cert, | ||
309 | "tbsCertificate.issuer.rdnSequence", oid, | ||
310 | indx, raw_flag, buf, sizeof_buf); | ||
311 | } | ||
312 | |||
313 | /** | ||
314 | * gnutls_x509_crt_get_issuer_dn_oid - This function returns the Certificate's issuer distinguished name OIDs | ||
315 | * @cert: should contain a gnutls_x509_crt_t structure | ||
316 | * @indx: This specifies which OID to return. Use zero to get the first one. | ||
317 | * @oid: a pointer to a buffer to hold the OID (may be null) | ||
318 | * @sizeof_oid: initially holds the size of @oid | ||
319 | * | ||
320 | * This function will extract the OIDs of the name of the Certificate | ||
321 | * issuer specified by the given index. | ||
322 | * | ||
323 | * If @oid is null then only the size will be filled. | ||
324 | * | ||
325 | * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not | ||
326 | * long enough, and in that case the *sizeof_oid will be updated with | ||
327 | * the required size. On success 0 is returned. | ||
328 | * | ||
329 | **/ | ||
330 | int | ||
331 | gnutls_x509_crt_get_issuer_dn_oid (gnutls_x509_crt_t cert, | ||
332 | int indx, void *oid, size_t * sizeof_oid) | ||
333 | { | ||
334 | if (cert == NULL) | ||
335 | { | ||
336 | gnutls_assert (); | ||
337 | return GNUTLS_E_INVALID_REQUEST; | ||
338 | } | ||
339 | |||
340 | return _gnutls_x509_get_dn_oid (cert->cert, | ||
341 | "tbsCertificate.issuer.rdnSequence", indx, | ||
342 | oid, sizeof_oid); | ||
343 | } | ||
344 | |||
345 | /** | ||
346 | * gnutls_x509_crt_get_dn - This function returns the Certificate's distinguished name | ||
347 | * @cert: should contain a gnutls_x509_crt_t structure | ||
348 | * @buf: a pointer to a structure to hold the name (may be null) | ||
349 | * @sizeof_buf: initially holds the size of @buf | ||
350 | * | ||
351 | * This function will copy the name of the Certificate in the | ||
352 | * provided buffer. The name will be in the form | ||
353 | * "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253. The output string | ||
354 | * will be ASCII or UTF-8 encoded, depending on the certificate data. | ||
355 | * | ||
356 | * If @buf is null then only the size will be filled. | ||
357 | * | ||
358 | * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not | ||
359 | * long enough, and in that case the *sizeof_buf will be updated with | ||
360 | * the required size. On success 0 is returned. | ||
361 | * | ||
362 | **/ | ||
363 | int | ||
364 | gnutls_x509_crt_get_dn (gnutls_x509_crt_t cert, | ||
365 | char *buf, size_t * sizeof_buf) | ||
366 | { | ||
367 | if (cert == NULL) | ||
368 | { | ||
369 | gnutls_assert (); | ||
370 | return GNUTLS_E_INVALID_REQUEST; | ||
371 | } | ||
372 | |||
373 | return _gnutls_x509_parse_dn (cert->cert, | ||
374 | "tbsCertificate.subject.rdnSequence", buf, | ||
375 | sizeof_buf); | ||
376 | } | ||
377 | |||
378 | /** | ||
379 | * gnutls_x509_crt_get_dn_by_oid - This function returns the Certificate's distinguished name | ||
380 | * @cert: should contain a gnutls_x509_crt_t structure | ||
381 | * @oid: holds an Object Identified in null terminated string | ||
382 | * @indx: In case multiple same OIDs exist in the RDN, this specifies which to send. Use zero to get the first one. | ||
383 | * @raw_flag: If non zero returns the raw DER data of the DN part. | ||
384 | * @buf: a pointer where the DN part will be copied (may be null). | ||
385 | * @sizeof_buf: initially holds the size of @buf | ||
386 | * | ||
387 | * This function will extract the part of the name of the Certificate | ||
388 | * subject specified by the given OID. The output, if the raw flag is not | ||
389 | * used, will be encoded as described in RFC2253. Thus a string that is | ||
390 | * ASCII or UTF-8 encoded, depending on the certificate data. | ||
391 | * | ||
392 | * Some helper macros with popular OIDs can be found in gnutls/x509.h | ||
393 | * If raw flag is zero, this function will only return known OIDs as | ||
394 | * text. Other OIDs will be DER encoded, as described in RFC2253 -- | ||
395 | * in hex format with a '\#' prefix. You can check about known OIDs | ||
396 | * using gnutls_x509_dn_oid_known(). | ||
397 | * | ||
398 | * If @buf is null then only the size will be filled. | ||
399 | * | ||
400 | * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not | ||
401 | * long enough, and in that case the *sizeof_buf will be updated with | ||
402 | * the required size. On success 0 is returned. | ||
403 | * | ||
404 | **/ | ||
405 | int | ||
406 | gnutls_x509_crt_get_dn_by_oid (gnutls_x509_crt_t cert, | ||
407 | const char *oid, | ||
408 | int indx, | ||
409 | unsigned int raw_flag, | ||
410 | void *buf, size_t * sizeof_buf) | ||
411 | { | ||
412 | if (cert == NULL) | ||
413 | { | ||
414 | gnutls_assert (); | ||
415 | return GNUTLS_E_INVALID_REQUEST; | ||
416 | } | ||
417 | |||
418 | return _gnutls_x509_parse_dn_oid (cert->cert, | ||
419 | "tbsCertificate.subject.rdnSequence", oid, | ||
420 | indx, raw_flag, buf, sizeof_buf); | ||
421 | } | ||
422 | |||
423 | /** | ||
424 | * gnutls_x509_crt_get_dn_oid - This function returns the Certificate's subject distinguished name OIDs | ||
425 | * @cert: should contain a gnutls_x509_crt_t structure | ||
426 | * @indx: This specifies which OID to return. Use zero to get the first one. | ||
427 | * @oid: a pointer to a buffer to hold the OID (may be null) | ||
428 | * @sizeof_oid: initially holds the size of @oid | ||
429 | * | ||
430 | * This function will extract the OIDs of the name of the Certificate | ||
431 | * subject specified by the given index. | ||
432 | * | ||
433 | * If oid is null then only the size will be filled. | ||
434 | * | ||
435 | * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not | ||
436 | * long enough, and in that case the *sizeof_oid will be updated with | ||
437 | * the required size. On success 0 is returned. | ||
438 | * | ||
439 | **/ | ||
440 | int | ||
441 | gnutls_x509_crt_get_dn_oid (gnutls_x509_crt_t cert, | ||
442 | int indx, void *oid, size_t * sizeof_oid) | ||
443 | { | ||
444 | if (cert == NULL) | ||
445 | { | ||
446 | gnutls_assert (); | ||
447 | return GNUTLS_E_INVALID_REQUEST; | ||
448 | } | ||
449 | |||
450 | return _gnutls_x509_get_dn_oid (cert->cert, | ||
451 | "tbsCertificate.subject.rdnSequence", indx, | ||
452 | oid, sizeof_oid); | ||
453 | } | ||
454 | |||
455 | /** | ||
456 | * gnutls_x509_crt_get_signature_algorithm - This function returns the Certificate's signature algorithm | ||
457 | * @cert: should contain a gnutls_x509_crt_t structure | ||
458 | * | ||
459 | * This function will return a value of the gnutls_sign_algorithm_t enumeration that | ||
460 | * is the signature algorithm. | ||
461 | * | ||
462 | * Returns a negative value on error. | ||
463 | * | ||
464 | **/ | ||
465 | int | ||
466 | gnutls_x509_crt_get_signature_algorithm (gnutls_x509_crt_t cert) | ||
467 | { | ||
468 | int result; | ||
469 | gnutls_datum_t sa; | ||
470 | |||
471 | if (cert == NULL) | ||
472 | { | ||
473 | gnutls_assert (); | ||
474 | return GNUTLS_E_INVALID_REQUEST; | ||
475 | } | ||
476 | |||
477 | /* Read the signature algorithm. Note that parameters are not | ||
478 | * read. They will be read from the issuer's certificate if needed. | ||
479 | */ | ||
480 | result = | ||
481 | _gnutls_x509_read_value (cert->cert, "signatureAlgorithm.algorithm", &sa, | ||
482 | 0); | ||
483 | |||
484 | if (result < 0) | ||
485 | { | ||
486 | gnutls_assert (); | ||
487 | return result; | ||
488 | } | ||
489 | |||
490 | result = _gnutls_x509_oid2sign_algorithm (sa.data); | ||
491 | |||
492 | _gnutls_free_datum (&sa); | ||
493 | |||
494 | return result; | ||
495 | } | ||
496 | |||
497 | /** | ||
498 | * gnutls_x509_crt_get_signature - Returns the Certificate's signature | ||
499 | * @cert: should contain a gnutls_x509_crt_t structure | ||
500 | * @sig: a pointer where the signature part will be copied (may be null). | ||
501 | * @sizeof_sig: initially holds the size of @sig | ||
502 | * | ||
503 | * This function will extract the signature field of a certificate. | ||
504 | * | ||
505 | * Returns 0 on success, and a negative value on error. | ||
506 | **/ | ||
507 | int | ||
508 | gnutls_x509_crt_get_signature (gnutls_x509_crt_t cert, | ||
509 | char *sig, size_t * sizeof_sig) | ||
510 | { | ||
511 | int result; | ||
512 | int bits, len; | ||
513 | |||
514 | if (cert == NULL) | ||
515 | { | ||
516 | gnutls_assert (); | ||
517 | return GNUTLS_E_INVALID_REQUEST; | ||
518 | } | ||
519 | |||
520 | bits = 0; | ||
521 | result = asn1_read_value (cert->cert, "signature", NULL, &bits); | ||
522 | if (result != ASN1_MEM_ERROR) | ||
523 | { | ||
524 | gnutls_assert (); | ||
525 | return _gnutls_asn2err (result); | ||
526 | } | ||
527 | |||
528 | if (bits % 8 != 0) | ||
529 | { | ||
530 | gnutls_assert (); | ||
531 | return GNUTLS_E_CERTIFICATE_ERROR; | ||
532 | } | ||
533 | |||
534 | len = bits / 8; | ||
535 | |||
536 | if (*sizeof_sig < len) | ||
537 | { | ||
538 | *sizeof_sig = bits / 8; | ||
539 | return GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
540 | } | ||
541 | |||
542 | result = asn1_read_value (cert->cert, "signature", sig, &len); | ||
543 | if (result != ASN1_SUCCESS) | ||
544 | { | ||
545 | gnutls_assert (); | ||
546 | return _gnutls_asn2err (result); | ||
547 | } | ||
548 | |||
549 | return 0; | ||
550 | } | ||
551 | |||
552 | /** | ||
553 | * gnutls_x509_crt_get_version - This function returns the Certificate's version number | ||
554 | * @cert: should contain a gnutls_x509_crt_t structure | ||
555 | * | ||
556 | * This function will return the version of the specified Certificate. | ||
557 | * | ||
558 | * Returns a negative value on error. | ||
559 | * | ||
560 | **/ | ||
561 | int | ||
562 | gnutls_x509_crt_get_version (gnutls_x509_crt_t cert) | ||
563 | { | ||
564 | opaque version[5]; | ||
565 | int len, result; | ||
566 | |||
567 | if (cert == NULL) | ||
568 | { | ||
569 | gnutls_assert (); | ||
570 | return GNUTLS_E_INVALID_REQUEST; | ||
571 | } | ||
572 | |||
573 | len = sizeof (version); | ||
574 | if ((result = | ||
575 | asn1_read_value (cert->cert, "tbsCertificate.version", version, | ||
576 | &len)) != ASN1_SUCCESS) | ||
577 | { | ||
578 | |||
579 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
580 | return 1; /* the DEFAULT version */ | ||
581 | gnutls_assert (); | ||
582 | return _gnutls_asn2err (result); | ||
583 | } | ||
584 | |||
585 | return (int) version[0] + 1; | ||
586 | } | ||
587 | |||
588 | /** | ||
589 | * gnutls_x509_crt_get_activation_time - This function returns the Certificate's activation time | ||
590 | * @cert: should contain a gnutls_x509_crt_t structure | ||
591 | * | ||
592 | * This function will return the time this Certificate was or will be activated. | ||
593 | * | ||
594 | * Returns (time_t)-1 on error. | ||
595 | * | ||
596 | **/ | ||
597 | time_t | ||
598 | gnutls_x509_crt_get_activation_time (gnutls_x509_crt_t cert) | ||
599 | { | ||
600 | if (cert == NULL) | ||
601 | { | ||
602 | gnutls_assert (); | ||
603 | return (time_t) - 1; | ||
604 | } | ||
605 | |||
606 | return _gnutls_x509_get_time (cert->cert, | ||
607 | "tbsCertificate.validity.notBefore"); | ||
608 | } | ||
609 | |||
610 | /** | ||
611 | * gnutls_x509_crt_get_expiration_time - This function returns the Certificate's expiration time | ||
612 | * @cert: should contain a gnutls_x509_crt_t structure | ||
613 | * | ||
614 | * This function will return the time this Certificate was or will be expired. | ||
615 | * | ||
616 | * Returns (time_t)-1 on error. | ||
617 | * | ||
618 | **/ | ||
619 | time_t | ||
620 | gnutls_x509_crt_get_expiration_time (gnutls_x509_crt_t cert) | ||
621 | { | ||
622 | if (cert == NULL) | ||
623 | { | ||
624 | gnutls_assert (); | ||
625 | return (time_t) - 1; | ||
626 | } | ||
627 | |||
628 | return _gnutls_x509_get_time (cert->cert, | ||
629 | "tbsCertificate.validity.notAfter"); | ||
630 | } | ||
631 | |||
632 | /** | ||
633 | * gnutls_x509_crt_get_serial - This function returns the certificate's serial number | ||
634 | * @cert: should contain a gnutls_x509_crt_t structure | ||
635 | * @result: The place where the serial number will be copied | ||
636 | * @result_size: Holds the size of the result field. | ||
637 | * | ||
638 | * This function will return the X.509 certificate's serial number. | ||
639 | * This is obtained by the X509 Certificate serialNumber | ||
640 | * field. Serial is not always a 32 or 64bit number. Some CAs use | ||
641 | * large serial numbers, thus it may be wise to handle it as something | ||
642 | * opaque. | ||
643 | * | ||
644 | * Returns 0 on success and a negative value in case of an error. | ||
645 | * | ||
646 | **/ | ||
647 | int | ||
648 | gnutls_x509_crt_get_serial (gnutls_x509_crt_t cert, | ||
649 | void *result, size_t * result_size) | ||
650 | { | ||
651 | int ret, len; | ||
652 | |||
653 | if (cert == NULL) | ||
654 | { | ||
655 | gnutls_assert (); | ||
656 | return GNUTLS_E_INVALID_REQUEST; | ||
657 | } | ||
658 | |||
659 | len = *result_size; | ||
660 | ret | ||
661 | = | ||
662 | asn1_read_value (cert->cert, "tbsCertificate.serialNumber", result, &len); | ||
663 | *result_size = len; | ||
664 | |||
665 | if (ret != ASN1_SUCCESS) | ||
666 | { | ||
667 | gnutls_assert (); | ||
668 | return _gnutls_asn2err (ret); | ||
669 | } | ||
670 | |||
671 | return 0; | ||
672 | } | ||
673 | |||
674 | /** | ||
675 | * gnutls_x509_crt_get_subject_key_id - This function returns the certificate's key identifier | ||
676 | * @cert: should contain a gnutls_x509_crt_t structure | ||
677 | * @ret: The place where the identifier will be copied | ||
678 | * @ret_size: Holds the size of the result field. | ||
679 | * @critical: will be non zero if the extension is marked as critical (may be null) | ||
680 | * | ||
681 | * This function will return the X.509v3 certificate's subject key identifier. | ||
682 | * This is obtained by the X.509 Subject Key identifier extension | ||
683 | * field (2.5.29.14). | ||
684 | * | ||
685 | * Returns 0 on success and a negative value in case of an error. | ||
686 | * | ||
687 | **/ | ||
688 | int | ||
689 | gnutls_x509_crt_get_subject_key_id (gnutls_x509_crt_t cert, | ||
690 | void *ret, | ||
691 | size_t * ret_size, unsigned int *critical) | ||
692 | { | ||
693 | int result, len; | ||
694 | gnutls_datum_t id; | ||
695 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
696 | |||
697 | if (cert == NULL) | ||
698 | { | ||
699 | gnutls_assert (); | ||
700 | return GNUTLS_E_INVALID_REQUEST; | ||
701 | } | ||
702 | |||
703 | if (ret) | ||
704 | memset (ret, 0, *ret_size); | ||
705 | else | ||
706 | *ret_size = 0; | ||
707 | |||
708 | if ((result = _gnutls_x509_crt_get_extension (cert, "2.5.29.14", 0, &id, | ||
709 | critical)) < 0) | ||
710 | { | ||
711 | return result; | ||
712 | } | ||
713 | |||
714 | if (id.size == 0 || id.data == NULL) | ||
715 | { | ||
716 | gnutls_assert (); | ||
717 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
718 | } | ||
719 | |||
720 | result = | ||
721 | asn1_create_element (_gnutls_get_pkix (), "PKIX1.SubjectKeyIdentifier", | ||
722 | &c2); | ||
723 | if (result != ASN1_SUCCESS) | ||
724 | { | ||
725 | gnutls_assert (); | ||
726 | _gnutls_free_datum (&id); | ||
727 | return _gnutls_asn2err (result); | ||
728 | } | ||
729 | |||
730 | result = asn1_der_decoding (&c2, id.data, id.size, NULL); | ||
731 | _gnutls_free_datum (&id); | ||
732 | |||
733 | if (result != ASN1_SUCCESS) | ||
734 | { | ||
735 | gnutls_assert (); | ||
736 | asn1_delete_structure (&c2); | ||
737 | return _gnutls_asn2err (result); | ||
738 | } | ||
739 | |||
740 | len = *ret_size; | ||
741 | result = asn1_read_value (c2, "", ret, &len); | ||
742 | |||
743 | *ret_size = len; | ||
744 | asn1_delete_structure (&c2); | ||
745 | |||
746 | if (result == ASN1_VALUE_NOT_FOUND || result == ASN1_ELEMENT_NOT_FOUND) | ||
747 | { | ||
748 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
749 | } | ||
750 | |||
751 | if (result != ASN1_SUCCESS) | ||
752 | { | ||
753 | gnutls_assert (); | ||
754 | return _gnutls_asn2err (result); | ||
755 | } | ||
756 | |||
757 | return 0; | ||
758 | } | ||
759 | |||
760 | /** | ||
761 | * gnutls_x509_crt_get_authority_key_id - This function returns the certificate authority's identifier | ||
762 | * @cert: should contain a gnutls_x509_crt_t structure | ||
763 | * @result: The place where the identifier will be copied | ||
764 | * @result_size: Holds the size of the result field. | ||
765 | * @critical: will be non zero if the extension is marked as critical (may be null) | ||
766 | * | ||
767 | * This function will return the X.509v3 certificate authority's key identifier. | ||
768 | * This is obtained by the X.509 Authority Key identifier extension | ||
769 | * field (2.5.29.35). Note that this function only returns the keyIdentifier | ||
770 | * field of the extension. | ||
771 | * | ||
772 | * Returns 0 on success and a negative value in case of an error. | ||
773 | * | ||
774 | **/ | ||
775 | int | ||
776 | gnutls_x509_crt_get_authority_key_id (gnutls_x509_crt_t cert, | ||
777 | void *ret, | ||
778 | size_t * ret_size, | ||
779 | unsigned int *critical) | ||
780 | { | ||
781 | int result, len; | ||
782 | gnutls_datum_t id; | ||
783 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
784 | |||
785 | if (cert == NULL) | ||
786 | { | ||
787 | gnutls_assert (); | ||
788 | return GNUTLS_E_INVALID_REQUEST; | ||
789 | } | ||
790 | |||
791 | if (ret) | ||
792 | memset (ret, 0, *ret_size); | ||
793 | else | ||
794 | *ret_size = 0; | ||
795 | |||
796 | if ((result = _gnutls_x509_crt_get_extension (cert, "2.5.29.35", 0, &id, | ||
797 | critical)) < 0) | ||
798 | { | ||
799 | return result; | ||
800 | } | ||
801 | |||
802 | if (id.size == 0 || id.data == NULL) | ||
803 | { | ||
804 | gnutls_assert (); | ||
805 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
806 | } | ||
807 | |||
808 | result = | ||
809 | asn1_create_element (_gnutls_get_pkix (), "PKIX1.AuthorityKeyIdentifier", | ||
810 | &c2); | ||
811 | if (result != ASN1_SUCCESS) | ||
812 | { | ||
813 | gnutls_assert (); | ||
814 | _gnutls_free_datum (&id); | ||
815 | return _gnutls_asn2err (result); | ||
816 | } | ||
817 | |||
818 | result = asn1_der_decoding (&c2, id.data, id.size, NULL); | ||
819 | _gnutls_free_datum (&id); | ||
820 | |||
821 | if (result != ASN1_SUCCESS) | ||
822 | { | ||
823 | gnutls_assert (); | ||
824 | asn1_delete_structure (&c2); | ||
825 | return _gnutls_asn2err (result); | ||
826 | } | ||
827 | |||
828 | len = *ret_size; | ||
829 | result = asn1_read_value (c2, "keyIdentifier", ret, &len); | ||
830 | |||
831 | *ret_size = len; | ||
832 | asn1_delete_structure (&c2); | ||
833 | |||
834 | if (result == ASN1_VALUE_NOT_FOUND || result == ASN1_ELEMENT_NOT_FOUND) | ||
835 | { | ||
836 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
837 | } | ||
838 | |||
839 | if (result != ASN1_SUCCESS) | ||
840 | { | ||
841 | gnutls_assert (); | ||
842 | return _gnutls_asn2err (result); | ||
843 | } | ||
844 | |||
845 | return 0; | ||
846 | } | ||
847 | |||
848 | /** | ||
849 | * gnutls_x509_crt_get_pk_algorithm - This function returns the certificate's PublicKey algorithm | ||
850 | * @cert: should contain a gnutls_x509_crt_t structure | ||
851 | * @bits: if bits is non null it will hold the size of the parameters' in bits | ||
852 | * | ||
853 | * This function will return the public key algorithm of an X.509 | ||
854 | * certificate. | ||
855 | * | ||
856 | * If bits is non null, it should have enough size to hold the parameters | ||
857 | * size in bits. For RSA the bits returned is the modulus. | ||
858 | * For DSA the bits returned are of the public | ||
859 | * exponent. | ||
860 | * | ||
861 | * Returns a member of the gnutls_pk_algorithm_t enumeration on success, | ||
862 | * or a negative value on error. | ||
863 | * | ||
864 | **/ | ||
865 | int | ||
866 | gnutls_x509_crt_get_pk_algorithm (gnutls_x509_crt_t cert, unsigned int *bits) | ||
867 | { | ||
868 | int result; | ||
869 | |||
870 | if (cert == NULL) | ||
871 | { | ||
872 | gnutls_assert (); | ||
873 | return GNUTLS_E_INVALID_REQUEST; | ||
874 | } | ||
875 | |||
876 | result = _gnutls_x509_get_pk_algorithm (cert->cert, | ||
877 | "tbsCertificate.subjectPublicKeyInfo", | ||
878 | bits); | ||
879 | |||
880 | if (result < 0) | ||
881 | { | ||
882 | gnutls_assert (); | ||
883 | return result; | ||
884 | } | ||
885 | |||
886 | return result; | ||
887 | |||
888 | } | ||
889 | |||
890 | inline static int | ||
891 | is_type_printable (int type) | ||
892 | { | ||
893 | if (type == GNUTLS_SAN_DNSNAME || type == GNUTLS_SAN_RFC822NAME || type | ||
894 | == GNUTLS_SAN_URI) | ||
895 | return 1; | ||
896 | else | ||
897 | return 0; | ||
898 | } | ||
899 | |||
900 | #define XMPP_OID "1.3.6.1.5.5.7.8.5" | ||
901 | |||
902 | /* returns the type and the name on success. | ||
903 | * Type is also returned as a parameter in case of an error. | ||
904 | */ | ||
905 | static int | ||
906 | parse_general_name (ASN1_TYPE src, | ||
907 | const char *src_name, | ||
908 | int seq, | ||
909 | void *name, | ||
910 | size_t * name_size, | ||
911 | unsigned int *ret_type, int othername_oid) | ||
912 | { | ||
913 | int len; | ||
914 | char nptr[MAX_NAME_SIZE]; | ||
915 | int result; | ||
916 | opaque choice_type[128]; | ||
917 | gnutls_x509_subject_alt_name_t type; | ||
918 | |||
919 | seq++; /* 0->1, 1->2 etc */ | ||
920 | |||
921 | if (src_name[0] != 0) | ||
922 | snprintf (nptr, sizeof (nptr), "%s.?%u", src_name, seq); | ||
923 | else | ||
924 | snprintf (nptr, sizeof (nptr), "?%u", seq); | ||
925 | |||
926 | len = sizeof (choice_type); | ||
927 | result = asn1_read_value (src, nptr, choice_type, &len); | ||
928 | |||
929 | if (result == ASN1_VALUE_NOT_FOUND || result == ASN1_ELEMENT_NOT_FOUND) | ||
930 | { | ||
931 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
932 | } | ||
933 | |||
934 | if (result != ASN1_SUCCESS) | ||
935 | { | ||
936 | gnutls_assert (); | ||
937 | return _gnutls_asn2err (result); | ||
938 | } | ||
939 | |||
940 | type = _gnutls_x509_san_find_type (choice_type); | ||
941 | if (type == (gnutls_x509_subject_alt_name_t) - 1) | ||
942 | { | ||
943 | gnutls_assert (); | ||
944 | return GNUTLS_E_X509_UNKNOWN_SAN; | ||
945 | } | ||
946 | |||
947 | if (ret_type) | ||
948 | *ret_type = type; | ||
949 | |||
950 | if (type == GNUTLS_SAN_OTHERNAME) | ||
951 | { | ||
952 | if (othername_oid) | ||
953 | _gnutls_str_cat (nptr, sizeof (nptr), ".otherName.type-id"); | ||
954 | else | ||
955 | _gnutls_str_cat (nptr, sizeof (nptr), ".otherName.value"); | ||
956 | |||
957 | len = *name_size; | ||
958 | result = asn1_read_value (src, nptr, name, &len); | ||
959 | *name_size = len; | ||
960 | |||
961 | if (result == ASN1_MEM_ERROR) | ||
962 | return GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
963 | |||
964 | if (result != ASN1_SUCCESS) | ||
965 | { | ||
966 | gnutls_assert (); | ||
967 | return _gnutls_asn2err (result); | ||
968 | } | ||
969 | |||
970 | if (othername_oid) | ||
971 | { | ||
972 | if (len > strlen (XMPP_OID) && strcmp (name, XMPP_OID) == 0) | ||
973 | type = GNUTLS_SAN_OTHERNAME_XMPP; | ||
974 | } | ||
975 | else | ||
976 | { | ||
977 | char oid[42]; | ||
978 | |||
979 | if (src_name[0] != 0) | ||
980 | snprintf (nptr, sizeof (nptr), "%s.?%u.otherName.type-id", | ||
981 | src_name, seq); | ||
982 | else | ||
983 | snprintf (nptr, sizeof (nptr), "?%u.otherName.type-id", seq); | ||
984 | |||
985 | len = sizeof (oid); | ||
986 | result = asn1_read_value (src, nptr, oid, &len); | ||
987 | if (result != ASN1_SUCCESS) | ||
988 | { | ||
989 | gnutls_assert (); | ||
990 | return _gnutls_asn2err (result); | ||
991 | } | ||
992 | |||
993 | if (len > strlen (XMPP_OID) && strcmp (oid, XMPP_OID) == 0) | ||
994 | { | ||
995 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
996 | |||
997 | result = | ||
998 | asn1_create_element (_gnutls_get_pkix (), "PKIX1.XmppAddr", | ||
999 | &c2); | ||
1000 | if (result != ASN1_SUCCESS) | ||
1001 | { | ||
1002 | gnutls_assert (); | ||
1003 | return _gnutls_asn2err (result); | ||
1004 | } | ||
1005 | |||
1006 | result = asn1_der_decoding (&c2, name, *name_size, NULL); | ||
1007 | if (result != ASN1_SUCCESS) | ||
1008 | { | ||
1009 | gnutls_assert (); | ||
1010 | asn1_delete_structure (&c2); | ||
1011 | return _gnutls_asn2err (result); | ||
1012 | } | ||
1013 | |||
1014 | result = asn1_read_value (c2, "", name, &len); | ||
1015 | *name_size = len; | ||
1016 | if (result != ASN1_SUCCESS) | ||
1017 | { | ||
1018 | gnutls_assert (); | ||
1019 | asn1_delete_structure (&c2); | ||
1020 | return _gnutls_asn2err (result); | ||
1021 | } | ||
1022 | asn1_delete_structure (&c2); | ||
1023 | } | ||
1024 | } | ||
1025 | } | ||
1026 | else if (type == GNUTLS_SAN_DN) | ||
1027 | { | ||
1028 | _gnutls_str_cat (nptr, sizeof (nptr), ".directoryName"); | ||
1029 | result = _gnutls_x509_parse_dn (src, nptr, name, name_size); | ||
1030 | if (result < 0) | ||
1031 | { | ||
1032 | gnutls_assert (); | ||
1033 | return result; | ||
1034 | } | ||
1035 | } | ||
1036 | else if (othername_oid) | ||
1037 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
1038 | else | ||
1039 | { | ||
1040 | size_t orig_name_size = *name_size; | ||
1041 | |||
1042 | _gnutls_str_cat (nptr, sizeof (nptr), "."); | ||
1043 | _gnutls_str_cat (nptr, sizeof (nptr), choice_type); | ||
1044 | |||
1045 | len = *name_size; | ||
1046 | result = asn1_read_value (src, nptr, name, &len); | ||
1047 | *name_size = len; | ||
1048 | |||
1049 | if (result == ASN1_MEM_ERROR) | ||
1050 | { | ||
1051 | if (is_type_printable (type)) | ||
1052 | (*name_size)++; | ||
1053 | return GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
1054 | } | ||
1055 | |||
1056 | if (result != ASN1_SUCCESS) | ||
1057 | { | ||
1058 | gnutls_assert (); | ||
1059 | return _gnutls_asn2err (result); | ||
1060 | } | ||
1061 | |||
1062 | if (is_type_printable (type)) | ||
1063 | { | ||
1064 | |||
1065 | if (len + 1 > orig_name_size) | ||
1066 | { | ||
1067 | gnutls_assert (); | ||
1068 | (*name_size)++; | ||
1069 | return GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
1070 | } | ||
1071 | |||
1072 | /* null terminate it */ | ||
1073 | ((char *) name)[*name_size] = 0; | ||
1074 | } | ||
1075 | |||
1076 | } | ||
1077 | |||
1078 | return type; | ||
1079 | } | ||
1080 | |||
1081 | static int | ||
1082 | get_subject_alt_name (gnutls_x509_crt_t cert, | ||
1083 | unsigned int seq, | ||
1084 | void *ret, | ||
1085 | size_t * ret_size, | ||
1086 | unsigned int *ret_type, | ||
1087 | unsigned int *critical, int othername_oid) | ||
1088 | { | ||
1089 | int result; | ||
1090 | gnutls_datum_t dnsname; | ||
1091 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
1092 | gnutls_x509_subject_alt_name_t type; | ||
1093 | |||
1094 | if (cert == NULL) | ||
1095 | { | ||
1096 | gnutls_assert (); | ||
1097 | return GNUTLS_E_INVALID_REQUEST; | ||
1098 | } | ||
1099 | |||
1100 | if (ret) | ||
1101 | memset (ret, 0, *ret_size); | ||
1102 | else | ||
1103 | *ret_size = 0; | ||
1104 | |||
1105 | if ((result = | ||
1106 | _gnutls_x509_crt_get_extension (cert, "2.5.29.17", 0, &dnsname, | ||
1107 | critical)) < 0) | ||
1108 | { | ||
1109 | return result; | ||
1110 | } | ||
1111 | |||
1112 | if (dnsname.size == 0 || dnsname.data == NULL) | ||
1113 | { | ||
1114 | gnutls_assert (); | ||
1115 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
1116 | } | ||
1117 | |||
1118 | result = | ||
1119 | asn1_create_element (_gnutls_get_pkix (), "PKIX1.SubjectAltName", &c2); | ||
1120 | if (result != ASN1_SUCCESS) | ||
1121 | { | ||
1122 | gnutls_assert (); | ||
1123 | _gnutls_free_datum (&dnsname); | ||
1124 | return _gnutls_asn2err (result); | ||
1125 | } | ||
1126 | |||
1127 | result = asn1_der_decoding (&c2, dnsname.data, dnsname.size, NULL); | ||
1128 | _gnutls_free_datum (&dnsname); | ||
1129 | |||
1130 | if (result != ASN1_SUCCESS) | ||
1131 | { | ||
1132 | gnutls_assert (); | ||
1133 | asn1_delete_structure (&c2); | ||
1134 | return _gnutls_asn2err (result); | ||
1135 | } | ||
1136 | |||
1137 | result = parse_general_name (c2, "", seq, ret, ret_size, ret_type, | ||
1138 | othername_oid); | ||
1139 | |||
1140 | asn1_delete_structure (&c2); | ||
1141 | |||
1142 | if (result < 0) | ||
1143 | { | ||
1144 | return result; | ||
1145 | } | ||
1146 | |||
1147 | type = result; | ||
1148 | |||
1149 | return type; | ||
1150 | } | ||
1151 | |||
1152 | /** | ||
1153 | * gnutls_x509_crt_get_subject_alt_name - Get certificate's alternative name, if any | ||
1154 | * @cert: should contain a gnutls_x509_crt_t structure | ||
1155 | * @seq: specifies the sequence number of the alt name (0 for the first one, 1 for the second etc.) | ||
1156 | * @ret: is the place where the alternative name will be copied to | ||
1157 | * @ret_size: holds the size of ret. | ||
1158 | * @critical: will be non zero if the extension is marked as critical (may be null) | ||
1159 | * | ||
1160 | * This function will return the alternative names, contained in the | ||
1161 | * given certificate. | ||
1162 | * | ||
1163 | * This is specified in X509v3 Certificate Extensions. GNUTLS will | ||
1164 | * return the Alternative name (2.5.29.17), or a negative error code. | ||
1165 | * | ||
1166 | * When the SAN type is otherName, it will extract the data in the | ||
1167 | * otherName's value field, and %GNUTLS_SAN_OTHERNAME is returned. | ||
1168 | * You may use gnutls_x509_crt_get_subject_alt_othername_oid() to get | ||
1169 | * the corresponding OID and the "virtual" SAN types (e.g., | ||
1170 | * %GNUTLS_SAN_OTHERNAME_XMPP). | ||
1171 | * | ||
1172 | * If an otherName OID is known, the data will be decoded. Otherwise | ||
1173 | * the returned data will be DER encoded, and you will have to decode | ||
1174 | * it yourself. Currently, only the RFC 3920 id-on-xmppAddr SAN is | ||
1175 | * recognized. | ||
1176 | * | ||
1177 | * Returns the alternative subject name type on success. The type is | ||
1178 | * one of the enumerated gnutls_x509_subject_alt_name_t. It will | ||
1179 | * return %GNUTLS_E_SHORT_MEMORY_BUFFER if @ret_size is not large | ||
1180 | * enough to hold the value. In that case @ret_size will be updated | ||
1181 | * with the required size. If the certificate does not have an | ||
1182 | * Alternative name with the specified sequence number then | ||
1183 | * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned. | ||
1184 | * | ||
1185 | **/ | ||
1186 | int | ||
1187 | gnutls_x509_crt_get_subject_alt_name (gnutls_x509_crt_t cert, | ||
1188 | unsigned int seq, | ||
1189 | void *ret, | ||
1190 | size_t * ret_size, | ||
1191 | unsigned int *critical) | ||
1192 | { | ||
1193 | return get_subject_alt_name (cert, seq, ret, ret_size, NULL, critical, 0); | ||
1194 | } | ||
1195 | |||
1196 | /** | ||
1197 | * gnutls_x509_crt_get_subject_alt_name2 - Get certificate's alternative name, if any | ||
1198 | * @cert: should contain a gnutls_x509_crt_t structure | ||
1199 | * @seq: specifies the sequence number of the alt name (0 for the first one, 1 for the second etc.) | ||
1200 | * @ret: is the place where the alternative name will be copied to | ||
1201 | * @ret_size: holds the size of ret. | ||
1202 | * @ret_type: holds the type of the alternative name (one of gnutls_x509_subject_alt_name_t). | ||
1203 | * @critical: will be non zero if the extension is marked as critical (may be null) | ||
1204 | * | ||
1205 | * This function will return the alternative names, contained in the | ||
1206 | * given certificate. It is the same as gnutls_x509_crt_get_subject_alt_name() | ||
1207 | * except for the fact that it will return the type of the alternative | ||
1208 | * name in @ret_type even if the function fails for some reason (i.e. | ||
1209 | * the buffer provided is not enough). | ||
1210 | * | ||
1211 | * The return values are the same as with gnutls_x509_crt_get_subject_alt_name(). | ||
1212 | * | ||
1213 | **/ | ||
1214 | int | ||
1215 | gnutls_x509_crt_get_subject_alt_name2 (gnutls_x509_crt_t cert, | ||
1216 | unsigned int seq, | ||
1217 | void *ret, | ||
1218 | size_t * ret_size, | ||
1219 | unsigned int *ret_type, | ||
1220 | unsigned int *critical) | ||
1221 | { | ||
1222 | return get_subject_alt_name (cert, seq, ret, ret_size, ret_type, critical, | ||
1223 | 0); | ||
1224 | } | ||
1225 | |||
1226 | /** | ||
1227 | * gnutls_x509_crt_get_subject_alt_othername_oid - Get SAN otherName OID | ||
1228 | * @cert: should contain a gnutls_x509_crt_t structure | ||
1229 | * @seq: specifies the sequence number of the alt name (0 for the first one, 1 for the second etc.) | ||
1230 | * @ret: is the place where the otherName OID will be copied to | ||
1231 | * @ret_size: holds the size of ret. | ||
1232 | * | ||
1233 | * This function will extract the type OID of an otherName Subject | ||
1234 | * Alternative Name, contained in the given certificate, and return | ||
1235 | * the type as an enumerated element. | ||
1236 | * | ||
1237 | * This function is only useful if | ||
1238 | * gnutls_x509_crt_get_subject_alt_name() returned | ||
1239 | * %GNUTLS_SAN_OTHERNAME. | ||
1240 | * | ||
1241 | * Returns the alternative subject name type on success. The type is | ||
1242 | * one of the enumerated gnutls_x509_subject_alt_name_t. For | ||
1243 | * supported OIDs, it will return one of the virtual | ||
1244 | * (GNUTLS_SAN_OTHERNAME_*) types, e.g. %GNUTLS_SAN_OTHERNAME_XMPP, | ||
1245 | * and %GNUTLS_SAN_OTHERNAME for unknown OIDs. It will return | ||
1246 | * %GNUTLS_E_SHORT_MEMORY_BUFFER if @ret_size is not large enough to | ||
1247 | * hold the value. In that case @ret_size will be updated with the | ||
1248 | * required size. If the certificate does not have an Alternative | ||
1249 | * name with the specified sequence number and with the otherName type | ||
1250 | * then %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned. | ||
1251 | **/ | ||
1252 | int | ||
1253 | gnutls_x509_crt_get_subject_alt_othername_oid (gnutls_x509_crt_t cert, | ||
1254 | unsigned int seq, | ||
1255 | void *ret, size_t * ret_size) | ||
1256 | { | ||
1257 | return get_subject_alt_name (cert, seq, ret, ret_size, NULL, NULL, 1); | ||
1258 | } | ||
1259 | |||
1260 | /** | ||
1261 | * gnutls_x509_crt_get_basic_constraints - This function returns the certificate basic constraints | ||
1262 | * @cert: should contain a gnutls_x509_crt_t structure | ||
1263 | * @critical: will be non zero if the extension is marked as critical | ||
1264 | * @ca: pointer to output integer indicating CA status, may be NULL, | ||
1265 | * value is 1 if the certificate CA flag is set, 0 otherwise. | ||
1266 | * @pathlen: pointer to output integer indicating path length (may be | ||
1267 | * NULL), non-negative values indicate a present pathLenConstraint | ||
1268 | * field and the actual value, -1 indicate that the field is absent. | ||
1269 | * | ||
1270 | * This function will read the certificate's basic constraints, and | ||
1271 | * return the certificates CA status. It reads the basicConstraints | ||
1272 | * X.509 extension (2.5.29.19). | ||
1273 | * | ||
1274 | * Return value: If the certificate is a CA a positive value will be | ||
1275 | * returned, or zero if the certificate does not have CA flag set. A | ||
1276 | * negative value may be returned in case of errors. If the | ||
1277 | * certificate does not contain the basicConstraints extension | ||
1278 | * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned. | ||
1279 | **/ | ||
1280 | int | ||
1281 | gnutls_x509_crt_get_basic_constraints (gnutls_x509_crt_t cert, | ||
1282 | unsigned int *critical, | ||
1283 | int *ca, int *pathlen) | ||
1284 | { | ||
1285 | int result; | ||
1286 | gnutls_datum_t basicConstraints; | ||
1287 | int tmp_ca; | ||
1288 | |||
1289 | if (cert == NULL) | ||
1290 | { | ||
1291 | gnutls_assert (); | ||
1292 | return GNUTLS_E_INVALID_REQUEST; | ||
1293 | } | ||
1294 | |||
1295 | if ((result = _gnutls_x509_crt_get_extension (cert, "2.5.29.19", 0, | ||
1296 | &basicConstraints, critical)) | ||
1297 | < 0) | ||
1298 | { | ||
1299 | return result; | ||
1300 | } | ||
1301 | |||
1302 | if (basicConstraints.size == 0 || basicConstraints.data == NULL) | ||
1303 | { | ||
1304 | gnutls_assert (); | ||
1305 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
1306 | } | ||
1307 | |||
1308 | result = _gnutls_x509_ext_extract_basicConstraints (&tmp_ca, pathlen, | ||
1309 | basicConstraints.data, | ||
1310 | basicConstraints.size); | ||
1311 | if (ca) | ||
1312 | *ca = tmp_ca; | ||
1313 | _gnutls_free_datum (&basicConstraints); | ||
1314 | |||
1315 | if (result < 0) | ||
1316 | { | ||
1317 | gnutls_assert (); | ||
1318 | return result; | ||
1319 | } | ||
1320 | |||
1321 | return tmp_ca; | ||
1322 | } | ||
1323 | |||
1324 | /** | ||
1325 | * gnutls_x509_crt_get_ca_status - This function returns the certificate CA status | ||
1326 | * @cert: should contain a gnutls_x509_crt_t structure | ||
1327 | * @critical: will be non zero if the extension is marked as critical | ||
1328 | * | ||
1329 | * This function will return certificates CA status, by reading the | ||
1330 | * basicConstraints X.509 extension (2.5.29.19). If the certificate is | ||
1331 | * a CA a positive value will be returned, or zero if the certificate | ||
1332 | * does not have CA flag set. | ||
1333 | * | ||
1334 | * Use gnutls_x509_crt_get_basic_constraints() if you want to read the | ||
1335 | * pathLenConstraint field too. | ||
1336 | * | ||
1337 | * A negative value may be returned in case of parsing error. | ||
1338 | * If the certificate does not contain the basicConstraints extension | ||
1339 | * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned. | ||
1340 | * | ||
1341 | **/ | ||
1342 | int | ||
1343 | gnutls_x509_crt_get_ca_status (gnutls_x509_crt_t cert, unsigned int *critical) | ||
1344 | { | ||
1345 | int ca, pathlen; | ||
1346 | return gnutls_x509_crt_get_basic_constraints (cert, critical, &ca, | ||
1347 | &pathlen); | ||
1348 | } | ||
1349 | |||
1350 | /** | ||
1351 | * gnutls_x509_crt_get_key_usage - This function returns the certificate's key usage | ||
1352 | * @cert: should contain a gnutls_x509_crt_t structure | ||
1353 | * @key_usage: where the key usage bits will be stored | ||
1354 | * @critical: will be non zero if the extension is marked as critical | ||
1355 | * | ||
1356 | * This function will return certificate's key usage, by reading the | ||
1357 | * keyUsage X.509 extension (2.5.29.15). The key usage value will ORed values of the: | ||
1358 | * GNUTLS_KEY_DIGITAL_SIGNATURE, GNUTLS_KEY_NON_REPUDIATION, | ||
1359 | * GNUTLS_KEY_KEY_ENCIPHERMENT, GNUTLS_KEY_DATA_ENCIPHERMENT, | ||
1360 | * GNUTLS_KEY_KEY_AGREEMENT, GNUTLS_KEY_KEY_CERT_SIGN, | ||
1361 | * GNUTLS_KEY_CRL_SIGN, GNUTLS_KEY_ENCIPHER_ONLY, | ||
1362 | * GNUTLS_KEY_DECIPHER_ONLY. | ||
1363 | * | ||
1364 | * A negative value may be returned in case of parsing error. | ||
1365 | * If the certificate does not contain the keyUsage extension | ||
1366 | * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned. | ||
1367 | * | ||
1368 | **/ | ||
1369 | int | ||
1370 | gnutls_x509_crt_get_key_usage (gnutls_x509_crt_t cert, | ||
1371 | unsigned int *key_usage, | ||
1372 | unsigned int *critical) | ||
1373 | { | ||
1374 | int result; | ||
1375 | gnutls_datum_t keyUsage; | ||
1376 | uint16_t _usage; | ||
1377 | |||
1378 | if (cert == NULL) | ||
1379 | { | ||
1380 | gnutls_assert (); | ||
1381 | return GNUTLS_E_INVALID_REQUEST; | ||
1382 | } | ||
1383 | |||
1384 | if ((result = | ||
1385 | _gnutls_x509_crt_get_extension (cert, "2.5.29.15", 0, &keyUsage, | ||
1386 | critical)) < 0) | ||
1387 | { | ||
1388 | return result; | ||
1389 | } | ||
1390 | |||
1391 | if (keyUsage.size == 0 || keyUsage.data == NULL) | ||
1392 | { | ||
1393 | gnutls_assert (); | ||
1394 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
1395 | } | ||
1396 | |||
1397 | result = _gnutls_x509_ext_extract_keyUsage (&_usage, keyUsage.data, | ||
1398 | keyUsage.size); | ||
1399 | _gnutls_free_datum (&keyUsage); | ||
1400 | |||
1401 | *key_usage = _usage; | ||
1402 | |||
1403 | if (result < 0) | ||
1404 | { | ||
1405 | gnutls_assert (); | ||
1406 | return result; | ||
1407 | } | ||
1408 | |||
1409 | return 0; | ||
1410 | } | ||
1411 | |||
1412 | /** | ||
1413 | * gnutls_x509_crt_get_proxy - This function returns the proxy certificate info | ||
1414 | * @cert: should contain a gnutls_x509_crt_t structure | ||
1415 | * @critical: will be non zero if the extension is marked as critical | ||
1416 | * @pathlen: pointer to output integer indicating path length (may be | ||
1417 | * NULL), non-negative values indicate a present pCPathLenConstraint | ||
1418 | * field and the actual value, -1 indicate that the field is absent. | ||
1419 | * | ||
1420 | * This function will read the certificate's basic constraints, and | ||
1421 | * return the certificates CA status. It reads the basicConstraints | ||
1422 | * X.509 extension (2.5.29.19). | ||
1423 | * | ||
1424 | * Return value: If the certificate is a CA a positive value will be | ||
1425 | * returned, or zero if the certificate does not have CA flag set. A | ||
1426 | * negative value may be returned in case of errors. If the | ||
1427 | * certificate does not contain the basicConstraints extension | ||
1428 | * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned. | ||
1429 | **/ | ||
1430 | int | ||
1431 | gnutls_x509_crt_get_proxy (gnutls_x509_crt_t cert, | ||
1432 | unsigned int *critical, | ||
1433 | int *pathlen, | ||
1434 | char **policyLanguage, | ||
1435 | char **policy, size_t * sizeof_policy) | ||
1436 | { | ||
1437 | int result; | ||
1438 | gnutls_datum_t proxyCertInfo; | ||
1439 | |||
1440 | if (cert == NULL) | ||
1441 | { | ||
1442 | gnutls_assert (); | ||
1443 | return GNUTLS_E_INVALID_REQUEST; | ||
1444 | } | ||
1445 | |||
1446 | if ((result = _gnutls_x509_crt_get_extension (cert, "1.3.6.1.5.5.7.1.14", 0, | ||
1447 | &proxyCertInfo, | ||
1448 | critical)) < 0) | ||
1449 | { | ||
1450 | return result; | ||
1451 | } | ||
1452 | |||
1453 | if (proxyCertInfo.size == 0 || proxyCertInfo.data == NULL) | ||
1454 | { | ||
1455 | gnutls_assert (); | ||
1456 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
1457 | } | ||
1458 | |||
1459 | result = _gnutls_x509_ext_extract_proxyCertInfo (pathlen, policyLanguage, | ||
1460 | policy, sizeof_policy, | ||
1461 | proxyCertInfo.data, | ||
1462 | proxyCertInfo.size); | ||
1463 | _gnutls_free_datum (&proxyCertInfo); | ||
1464 | if (result < 0) | ||
1465 | { | ||
1466 | gnutls_assert (); | ||
1467 | return result; | ||
1468 | } | ||
1469 | |||
1470 | return 0; | ||
1471 | } | ||
1472 | |||
1473 | /** | ||
1474 | * gnutls_x509_crt_get_extension_by_oid - This function returns the specified extension | ||
1475 | * @cert: should contain a gnutls_x509_crt_t structure | ||
1476 | * @oid: holds an Object Identified in null terminated string | ||
1477 | * @indx: In case multiple same OIDs exist in the extensions, this specifies which to send. Use zero to get the first one. | ||
1478 | * @buf: a pointer to a structure to hold the name (may be null) | ||
1479 | * @sizeof_buf: initially holds the size of @buf | ||
1480 | * @critical: will be non zero if the extension is marked as critical | ||
1481 | * | ||
1482 | * This function will return the extension specified by the OID in the certificate. | ||
1483 | * The extensions will be returned as binary data DER encoded, in the provided | ||
1484 | * buffer. | ||
1485 | * | ||
1486 | * A negative value may be returned in case of parsing error. | ||
1487 | * If the certificate does not contain the specified extension | ||
1488 | * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned. | ||
1489 | * | ||
1490 | **/ | ||
1491 | int | ||
1492 | gnutls_x509_crt_get_extension_by_oid (gnutls_x509_crt_t cert, | ||
1493 | const char *oid, | ||
1494 | int indx, | ||
1495 | void *buf, | ||
1496 | size_t * sizeof_buf, | ||
1497 | unsigned int *critical) | ||
1498 | { | ||
1499 | int result; | ||
1500 | gnutls_datum_t output; | ||
1501 | |||
1502 | if (cert == NULL) | ||
1503 | { | ||
1504 | gnutls_assert (); | ||
1505 | return GNUTLS_E_INVALID_REQUEST; | ||
1506 | } | ||
1507 | |||
1508 | if ((result = _gnutls_x509_crt_get_extension (cert, oid, indx, &output, | ||
1509 | critical)) < 0) | ||
1510 | { | ||
1511 | gnutls_assert (); | ||
1512 | return result; | ||
1513 | } | ||
1514 | |||
1515 | if (output.size == 0 || output.data == NULL) | ||
1516 | { | ||
1517 | gnutls_assert (); | ||
1518 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
1519 | } | ||
1520 | |||
1521 | if (output.size > (unsigned int) *sizeof_buf) | ||
1522 | { | ||
1523 | *sizeof_buf = output.size; | ||
1524 | _gnutls_free_datum (&output); | ||
1525 | return GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
1526 | } | ||
1527 | |||
1528 | *sizeof_buf = output.size; | ||
1529 | |||
1530 | if (buf) | ||
1531 | memcpy (buf, output.data, output.size); | ||
1532 | |||
1533 | _gnutls_free_datum (&output); | ||
1534 | |||
1535 | return 0; | ||
1536 | |||
1537 | } | ||
1538 | |||
1539 | /** | ||
1540 | * gnutls_x509_crt_get_extension_oid - This function returns the specified extension OID | ||
1541 | * @cert: should contain a gnutls_x509_crt_t structure | ||
1542 | * @indx: Specifies which extension OID to send. Use zero to get the first one. | ||
1543 | * @oid: a pointer to a structure to hold the OID (may be null) | ||
1544 | * @sizeof_oid: initially holds the size of @oid | ||
1545 | * | ||
1546 | * This function will return the requested extension OID in the certificate. | ||
1547 | * The extension OID will be stored as a string in the provided buffer. | ||
1548 | * | ||
1549 | * A negative value may be returned in case of parsing error. | ||
1550 | * If your have reached the last extension available | ||
1551 | * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned. | ||
1552 | * | ||
1553 | **/ | ||
1554 | int | ||
1555 | gnutls_x509_crt_get_extension_oid (gnutls_x509_crt_t cert, | ||
1556 | int indx, void *oid, size_t * sizeof_oid) | ||
1557 | { | ||
1558 | int result; | ||
1559 | |||
1560 | if (cert == NULL) | ||
1561 | { | ||
1562 | gnutls_assert (); | ||
1563 | return GNUTLS_E_INVALID_REQUEST; | ||
1564 | } | ||
1565 | |||
1566 | result = _gnutls_x509_crt_get_extension_oid (cert, indx, oid, sizeof_oid); | ||
1567 | if (result < 0) | ||
1568 | { | ||
1569 | return result; | ||
1570 | } | ||
1571 | |||
1572 | return 0; | ||
1573 | |||
1574 | } | ||
1575 | |||
1576 | /** | ||
1577 | * gnutls_x509_crt_get_extension_info - Get extension id and criticality | ||
1578 | * @cert: should contain a gnutls_x509_crt_t structure | ||
1579 | * @indx: Specifies which extension OID to send. Use zero to get the first one. | ||
1580 | * @oid: a pointer to a structure to hold the OID | ||
1581 | * @sizeof_oid: initially holds the size of @oid | ||
1582 | * @critical: output variable with critical flag, may be NULL. | ||
1583 | * | ||
1584 | * This function will return the requested extension OID in the | ||
1585 | * certificate, and the critical flag for it. The extension OID will | ||
1586 | * be stored as a string in the provided buffer. Use | ||
1587 | * gnutls_x509_crt_get_extension_data() to extract the data. | ||
1588 | * | ||
1589 | * Return 0 on success. A negative value may be returned in case of | ||
1590 | * parsing error. If you have reached the last extension available | ||
1591 | * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned. | ||
1592 | * | ||
1593 | **/ | ||
1594 | int | ||
1595 | gnutls_x509_crt_get_extension_info (gnutls_x509_crt_t cert, | ||
1596 | int indx, | ||
1597 | void *oid, | ||
1598 | size_t * sizeof_oid, int *critical) | ||
1599 | { | ||
1600 | int result; | ||
1601 | char str_critical[10]; | ||
1602 | char name[MAX_NAME_SIZE]; | ||
1603 | int len; | ||
1604 | |||
1605 | if (!cert) | ||
1606 | { | ||
1607 | gnutls_assert (); | ||
1608 | return GNUTLS_E_INVALID_REQUEST; | ||
1609 | } | ||
1610 | |||
1611 | snprintf (name, sizeof (name), "tbsCertificate.extensions.?%u.extnID", | ||
1612 | indx + 1); | ||
1613 | |||
1614 | len = *sizeof_oid; | ||
1615 | result = asn1_read_value (cert->cert, name, oid, &len); | ||
1616 | *sizeof_oid = len; | ||
1617 | |||
1618 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
1619 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
1620 | else if (result < 0) | ||
1621 | { | ||
1622 | gnutls_assert (); | ||
1623 | return _gnutls_asn2err (result); | ||
1624 | } | ||
1625 | |||
1626 | snprintf (name, sizeof (name), "tbsCertificate.extensions.?%u.critical", | ||
1627 | indx + 1); | ||
1628 | len = sizeof (str_critical); | ||
1629 | result = asn1_read_value (cert->cert, name, str_critical, &len); | ||
1630 | if (result < 0) | ||
1631 | { | ||
1632 | gnutls_assert (); | ||
1633 | return _gnutls_asn2err (result); | ||
1634 | } | ||
1635 | |||
1636 | if (critical) | ||
1637 | { | ||
1638 | if (str_critical[0] == 'T') | ||
1639 | *critical = 1; | ||
1640 | else | ||
1641 | *critical = 0; | ||
1642 | } | ||
1643 | |||
1644 | return 0; | ||
1645 | |||
1646 | } | ||
1647 | |||
1648 | /** | ||
1649 | * gnutls_x509_crt_get_extension_data - Get the specified extension data | ||
1650 | * @cert: should contain a gnutls_x509_crt_t structure | ||
1651 | * @indx: Specifies which extension OID to send. Use zero to get the first one. | ||
1652 | * @data: a pointer to a structure to hold the data (may be null) | ||
1653 | * @sizeof_data: initially holds the size of @oid | ||
1654 | * | ||
1655 | * This function will return the requested extension data in the | ||
1656 | * certificate. The extension data will be stored as a string in the | ||
1657 | * provided buffer. | ||
1658 | * | ||
1659 | * Use gnutls_x509_crt_get_extension_info() to extract the OID and | ||
1660 | * critical flag. Use gnutls_x509_crt_get_extension_by_oid() instead, | ||
1661 | * if you want to get data indexed by the extension OID rather than | ||
1662 | * sequence. | ||
1663 | * | ||
1664 | * Return 0 on success. A negative value may be returned in case of | ||
1665 | * parsing error. If you have reached the last extension available | ||
1666 | * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned. | ||
1667 | **/ | ||
1668 | int | ||
1669 | gnutls_x509_crt_get_extension_data (gnutls_x509_crt_t cert, | ||
1670 | int indx, | ||
1671 | void *data, size_t * sizeof_data) | ||
1672 | { | ||
1673 | int result, len; | ||
1674 | char name[MAX_NAME_SIZE]; | ||
1675 | |||
1676 | if (!cert) | ||
1677 | { | ||
1678 | gnutls_assert (); | ||
1679 | return GNUTLS_E_INVALID_REQUEST; | ||
1680 | } | ||
1681 | |||
1682 | snprintf (name, sizeof (name), "tbsCertificate.extensions.?%u.extnValue", | ||
1683 | indx + 1); | ||
1684 | |||
1685 | len = *sizeof_data; | ||
1686 | result = asn1_read_value (cert->cert, name, data, &len); | ||
1687 | *sizeof_data = len; | ||
1688 | |||
1689 | if (result == ASN1_ELEMENT_NOT_FOUND) | ||
1690 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
1691 | else if (result < 0) | ||
1692 | { | ||
1693 | gnutls_assert (); | ||
1694 | return _gnutls_asn2err (result); | ||
1695 | } | ||
1696 | |||
1697 | return 0; | ||
1698 | } | ||
1699 | |||
1700 | static int | ||
1701 | _gnutls_x509_crt_get_raw_dn2 (gnutls_x509_crt_t cert, | ||
1702 | const char *whom, gnutls_datum_t * start) | ||
1703 | { | ||
1704 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
1705 | int result, len1; | ||
1706 | int start1, end1; | ||
1707 | gnutls_datum_t signed_data = { NULL, | ||
1708 | 0 | ||
1709 | }; | ||
1710 | |||
1711 | /* get the issuer of 'cert' | ||
1712 | */ | ||
1713 | if ((result = | ||
1714 | asn1_create_element (_gnutls_get_pkix (), "PKIX1.TBSCertificate", | ||
1715 | &c2)) != ASN1_SUCCESS) | ||
1716 | { | ||
1717 | gnutls_assert (); | ||
1718 | return _gnutls_asn2err (result); | ||
1719 | } | ||
1720 | |||
1721 | result = _gnutls_x509_get_signed_data (cert->cert, "tbsCertificate", | ||
1722 | &signed_data); | ||
1723 | if (result < 0) | ||
1724 | { | ||
1725 | gnutls_assert (); | ||
1726 | goto cleanup; | ||
1727 | } | ||
1728 | |||
1729 | result = asn1_der_decoding (&c2, signed_data.data, signed_data.size, NULL); | ||
1730 | if (result != ASN1_SUCCESS) | ||
1731 | { | ||
1732 | gnutls_assert (); | ||
1733 | asn1_delete_structure (&c2); | ||
1734 | result = _gnutls_asn2err (result); | ||
1735 | goto cleanup; | ||
1736 | } | ||
1737 | |||
1738 | result = asn1_der_decoding_startEnd (c2, signed_data.data, signed_data.size, | ||
1739 | whom, &start1, &end1); | ||
1740 | |||
1741 | if (result != ASN1_SUCCESS) | ||
1742 | { | ||
1743 | gnutls_assert (); | ||
1744 | result = _gnutls_asn2err (result); | ||
1745 | goto cleanup; | ||
1746 | } | ||
1747 | |||
1748 | len1 = end1 - start1 + 1; | ||
1749 | |||
1750 | _gnutls_set_datum (start, &signed_data.data[start1], len1); | ||
1751 | |||
1752 | result = 0; | ||
1753 | |||
1754 | cleanup:asn1_delete_structure (&c2); | ||
1755 | _gnutls_free_datum (&signed_data); | ||
1756 | return result; | ||
1757 | } | ||
1758 | |||
1759 | /** | ||
1760 | * gnutls_x509_crt_get_raw_issuer_dn - This function returns the issuer's DN DER encoded | ||
1761 | * @cert: should contain a gnutls_x509_crt_t structure | ||
1762 | * @start: will hold the starting point of the DN | ||
1763 | * | ||
1764 | * This function will return a pointer to the DER encoded DN structure | ||
1765 | * and the length. | ||
1766 | * | ||
1767 | * Returns 0 on success or a negative value on error. | ||
1768 | * | ||
1769 | **/ | ||
1770 | int | ||
1771 | gnutls_x509_crt_get_raw_issuer_dn (gnutls_x509_crt_t cert, | ||
1772 | gnutls_datum_t * start) | ||
1773 | { | ||
1774 | return _gnutls_x509_crt_get_raw_dn2 (cert, "issuer", start); | ||
1775 | } | ||
1776 | |||
1777 | /** | ||
1778 | * gnutls_x509_crt_get_raw_dn - This function returns the subject's DN DER encoded | ||
1779 | * @cert: should contain a gnutls_x509_crt_t structure | ||
1780 | * @start: will hold the starting point of the DN | ||
1781 | * | ||
1782 | * This function will return a pointer to the DER encoded DN structure and | ||
1783 | * the length. | ||
1784 | * | ||
1785 | * Returns 0 on success, or a negative value on error. | ||
1786 | * | ||
1787 | **/ | ||
1788 | int | ||
1789 | gnutls_x509_crt_get_raw_dn (gnutls_x509_crt_t cert, gnutls_datum_t * start) | ||
1790 | { | ||
1791 | return _gnutls_x509_crt_get_raw_dn2 (cert, "subject", start); | ||
1792 | } | ||
1793 | |||
1794 | static int | ||
1795 | get_dn (gnutls_x509_crt_t cert, const char *whom, gnutls_x509_dn_t * dn) | ||
1796 | { | ||
1797 | *dn = asn1_find_node (cert->cert, whom); | ||
1798 | if (!*dn) | ||
1799 | return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND; | ||
1800 | return 0; | ||
1801 | } | ||
1802 | |||
1803 | /** | ||
1804 | * gnutls_x509_crt_get_subject: get opaque subject DN pointer | ||
1805 | * @cert: should contain a gnutls_x509_crt_t structure | ||
1806 | * @dn: output variable with pointer to opaque DN. | ||
1807 | * | ||
1808 | * Return the Certificate's Subject DN as an opaque data type. You | ||
1809 | * may use gnutls_x509_dn_get_rdn_ava() to decode the DN. | ||
1810 | * | ||
1811 | * Returns: Returns 0 on success, or an error code. | ||
1812 | **/ | ||
1813 | int | ||
1814 | gnutls_x509_crt_get_subject (gnutls_x509_crt_t cert, gnutls_x509_dn_t * dn) | ||
1815 | { | ||
1816 | return get_dn (cert, "tbsCertificate.subject.rdnSequence", dn); | ||
1817 | } | ||
1818 | |||
1819 | /** | ||
1820 | * gnutls_x509_crt_get_issuer: get opaque issuer DN pointer | ||
1821 | * @cert: should contain a gnutls_x509_crt_t structure | ||
1822 | * @dn: output variable with pointer to opaque DN | ||
1823 | * | ||
1824 | * Return the Certificate's Issuer DN as an opaque data type. You may | ||
1825 | * use gnutls_x509_dn_get_rdn_ava() to decode the DN. | ||
1826 | * | ||
1827 | * Note that @dn points into the @cert object, and thus you may not | ||
1828 | * deallocate @cert and continue to access @dn. | ||
1829 | * | ||
1830 | * Returns: Returns 0 on success, or an error code. | ||
1831 | **/ | ||
1832 | int | ||
1833 | gnutls_x509_crt_get_issuer (gnutls_x509_crt_t cert, gnutls_x509_dn_t * dn) | ||
1834 | { | ||
1835 | return get_dn (cert, "tbsCertificate.issuer.rdnSequence", dn); | ||
1836 | } | ||
1837 | |||
1838 | /** | ||
1839 | * gnutls_x509_dn_get_rdn_ava: | ||
1840 | * @dn: input variable with opaque DN pointer | ||
1841 | * @irdn: index of RDN | ||
1842 | * @iava: index of AVA. | ||
1843 | * @ava: Pointer to structure which will hold output information. | ||
1844 | * | ||
1845 | * Get pointers to data within the DN. | ||
1846 | * | ||
1847 | * Note that @ava will contain pointers into the @dn structure, so you | ||
1848 | * should not modify any data or deallocate it. Note also that the DN | ||
1849 | * in turn points into the original certificate structure, and thus | ||
1850 | * you may not deallocate the certificate and continue to access @dn. | ||
1851 | * | ||
1852 | * Returns: Returns 0 on success, or an error code. | ||
1853 | **/ | ||
1854 | int | ||
1855 | gnutls_x509_dn_get_rdn_ava (gnutls_x509_dn_t dn, | ||
1856 | int irdn, int iava, gnutls_x509_ava_st * ava) | ||
1857 | { | ||
1858 | ASN1_TYPE rdn, elem; | ||
1859 | long len; | ||
1860 | int lenlen, remlen, ret; | ||
1861 | char rbuf[MAX_NAME_SIZE]; | ||
1862 | unsigned char cls, *ptr; | ||
1863 | |||
1864 | iava++; | ||
1865 | irdn++; /* 0->1, 1->2 etc */ | ||
1866 | |||
1867 | snprintf (rbuf, sizeof (rbuf), "rdnSequence.?%d.?%d", irdn, iava); | ||
1868 | rdn = asn1_find_node (dn, rbuf); | ||
1869 | if (!rdn) | ||
1870 | { | ||
1871 | gnutls_assert (); | ||
1872 | return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND; | ||
1873 | } | ||
1874 | |||
1875 | snprintf (rbuf, sizeof (rbuf), "?%d.type", iava); | ||
1876 | elem = asn1_find_node (rdn, rbuf); | ||
1877 | if (!elem) | ||
1878 | { | ||
1879 | gnutls_assert (); | ||
1880 | return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND; | ||
1881 | } | ||
1882 | |||
1883 | ava->oid.data = elem->value; | ||
1884 | ava->oid.size = elem->value_len; | ||
1885 | |||
1886 | snprintf (rbuf, sizeof (rbuf), "?%d.value", iava); | ||
1887 | elem = asn1_find_node (rdn, rbuf); | ||
1888 | if (!elem) | ||
1889 | { | ||
1890 | gnutls_assert (); | ||
1891 | return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND; | ||
1892 | } | ||
1893 | |||
1894 | /* The value still has the previous tag's length bytes, plus the | ||
1895 | * current value's tag and length bytes. Decode them. | ||
1896 | */ | ||
1897 | |||
1898 | ptr = elem->value; | ||
1899 | remlen = elem->value_len; | ||
1900 | len = asn1_get_length_der (ptr, remlen, &lenlen); | ||
1901 | if (len < 0) | ||
1902 | { | ||
1903 | gnutls_assert (); | ||
1904 | return GNUTLS_E_ASN1_DER_ERROR; | ||
1905 | } | ||
1906 | |||
1907 | ptr += lenlen; | ||
1908 | remlen -= lenlen; | ||
1909 | ret = asn1_get_tag_der (ptr, remlen, &cls, &lenlen, &ava->value_tag); | ||
1910 | if (ret) | ||
1911 | { | ||
1912 | gnutls_assert (); | ||
1913 | return _gnutls_asn2err (ret); | ||
1914 | } | ||
1915 | |||
1916 | ptr += lenlen; | ||
1917 | remlen -= lenlen; | ||
1918 | |||
1919 | ava->value.size = asn1_get_length_der (ptr, remlen, &lenlen); | ||
1920 | if (ava->value.size < 0) | ||
1921 | { | ||
1922 | gnutls_assert (); | ||
1923 | return GNUTLS_E_ASN1_DER_ERROR; | ||
1924 | } | ||
1925 | ava->value.data = ptr + lenlen; | ||
1926 | |||
1927 | return 0; | ||
1928 | } | ||
1929 | |||
1930 | /** | ||
1931 | * gnutls_x509_crt_get_fingerprint - This function returns the Certificate's fingerprint | ||
1932 | * @cert: should contain a gnutls_x509_crt_t structure | ||
1933 | * @algo: is a digest algorithm | ||
1934 | * @buf: a pointer to a structure to hold the fingerprint (may be null) | ||
1935 | * @sizeof_buf: initially holds the size of @buf | ||
1936 | * | ||
1937 | * This function will calculate and copy the certificate's fingerprint | ||
1938 | * in the provided buffer. | ||
1939 | * | ||
1940 | * If the buffer is null then only the size will be filled. | ||
1941 | * | ||
1942 | * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is | ||
1943 | * not long enough, and in that case the *sizeof_buf will be updated | ||
1944 | * with the required size. On success 0 is returned. | ||
1945 | **/ | ||
1946 | int | ||
1947 | gnutls_x509_crt_get_fingerprint (gnutls_x509_crt_t cert, | ||
1948 | gnutls_digest_algorithm_t algo, | ||
1949 | void *buf, size_t * sizeof_buf) | ||
1950 | { | ||
1951 | opaque *cert_buf; | ||
1952 | int cert_buf_size; | ||
1953 | int result; | ||
1954 | gnutls_datum_t tmp; | ||
1955 | |||
1956 | if (sizeof_buf == 0 || cert == NULL) | ||
1957 | { | ||
1958 | return GNUTLS_E_INVALID_REQUEST; | ||
1959 | } | ||
1960 | |||
1961 | cert_buf_size = 0; | ||
1962 | asn1_der_coding (cert->cert, "", NULL, &cert_buf_size, NULL); | ||
1963 | |||
1964 | cert_buf = gnutls_alloca (cert_buf_size); | ||
1965 | if (cert_buf == NULL) | ||
1966 | { | ||
1967 | gnutls_assert (); | ||
1968 | return GNUTLS_E_MEMORY_ERROR; | ||
1969 | } | ||
1970 | |||
1971 | result = asn1_der_coding (cert->cert, "", cert_buf, &cert_buf_size, NULL); | ||
1972 | |||
1973 | if (result != ASN1_SUCCESS) | ||
1974 | { | ||
1975 | gnutls_assert (); | ||
1976 | gnutls_afree (cert_buf); | ||
1977 | return _gnutls_asn2err (result); | ||
1978 | } | ||
1979 | |||
1980 | tmp.data = cert_buf; | ||
1981 | tmp.size = cert_buf_size; | ||
1982 | |||
1983 | result = gnutls_fingerprint (algo, &tmp, buf, sizeof_buf); | ||
1984 | gnutls_afree (cert_buf); | ||
1985 | |||
1986 | return result; | ||
1987 | } | ||
1988 | |||
1989 | /** | ||
1990 | * gnutls_x509_crt_export - This function will export the certificate | ||
1991 | * @cert: Holds the certificate | ||
1992 | * @format: the format of output params. One of PEM or DER. | ||
1993 | * @output_data: will contain a certificate PEM or DER encoded | ||
1994 | * @output_data_size: holds the size of output_data (and will be | ||
1995 | * replaced by the actual size of parameters) | ||
1996 | * | ||
1997 | * This function will export the certificate to DER or PEM format. | ||
1998 | * | ||
1999 | * If the buffer provided is not long enough to hold the output, then | ||
2000 | * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will | ||
2001 | * be returned. | ||
2002 | * | ||
2003 | * If the structure is PEM encoded, it will have a header | ||
2004 | * of "BEGIN CERTIFICATE". | ||
2005 | * | ||
2006 | * Return value: In case of failure a negative value will be | ||
2007 | * returned, and 0 on success. | ||
2008 | **/ | ||
2009 | int | ||
2010 | gnutls_x509_crt_export (gnutls_x509_crt_t cert, | ||
2011 | gnutls_x509_crt_fmt_t format, | ||
2012 | void *output_data, size_t * output_data_size) | ||
2013 | { | ||
2014 | if (cert == NULL) | ||
2015 | { | ||
2016 | gnutls_assert (); | ||
2017 | return GNUTLS_E_INVALID_REQUEST; | ||
2018 | } | ||
2019 | |||
2020 | return _gnutls_x509_export_int (cert->cert, format, "CERTIFICATE", | ||
2021 | output_data, output_data_size); | ||
2022 | } | ||
2023 | |||
2024 | static int | ||
2025 | rsadsa_get_key_id (gnutls_x509_crt_t crt, | ||
2026 | int pk, | ||
2027 | unsigned char *output_data, size_t * output_data_size) | ||
2028 | { | ||
2029 | mpi_t params[MAX_PUBLIC_PARAMS_SIZE]; | ||
2030 | int params_size = MAX_PUBLIC_PARAMS_SIZE; | ||
2031 | int i, result = 0; | ||
2032 | gnutls_datum_t der = { NULL, | ||
2033 | 0 | ||
2034 | }; | ||
2035 | GNUTLS_HASH_HANDLE hd; | ||
2036 | |||
2037 | result = _gnutls_x509_crt_get_mpis (crt, params, ¶ms_size); | ||
2038 | if (result < 0) | ||
2039 | { | ||
2040 | gnutls_assert (); | ||
2041 | return result; | ||
2042 | } | ||
2043 | |||
2044 | if (pk == GNUTLS_PK_RSA) | ||
2045 | { | ||
2046 | result = _gnutls_x509_write_rsa_params (params, params_size, &der); | ||
2047 | if (result < 0) | ||
2048 | { | ||
2049 | gnutls_assert (); | ||
2050 | goto cleanup; | ||
2051 | } | ||
2052 | } | ||
2053 | else | ||
2054 | return GNUTLS_E_INTERNAL_ERROR; | ||
2055 | |||
2056 | hd = _gnutls_hash_init (GNUTLS_MAC_SHA1); | ||
2057 | if (hd == GNUTLS_HASH_FAILED) | ||
2058 | { | ||
2059 | gnutls_assert (); | ||
2060 | result = GNUTLS_E_INTERNAL_ERROR; | ||
2061 | goto cleanup; | ||
2062 | } | ||
2063 | |||
2064 | _gnutls_hash (hd, der.data, der.size); | ||
2065 | |||
2066 | _gnutls_hash_deinit (hd, output_data); | ||
2067 | *output_data_size = 20; | ||
2068 | |||
2069 | result = 0; | ||
2070 | |||
2071 | cleanup: | ||
2072 | |||
2073 | _gnutls_free_datum (&der); | ||
2074 | |||
2075 | /* release all allocated MPIs | ||
2076 | */ | ||
2077 | for (i = 0; i < params_size; i++) | ||
2078 | { | ||
2079 | _gnutls_mpi_release (¶ms[i]); | ||
2080 | } | ||
2081 | return result; | ||
2082 | } | ||
2083 | |||
2084 | /** | ||
2085 | * gnutls_x509_crt_get_key_id - Return unique ID of public key's parameters | ||
2086 | * @crt: Holds the certificate | ||
2087 | * @flags: should be 0 for now | ||
2088 | * @output_data: will contain the key ID | ||
2089 | * @output_data_size: holds the size of output_data (and will be | ||
2090 | * replaced by the actual size of parameters) | ||
2091 | * | ||
2092 | * This function will return a unique ID the depends on the public | ||
2093 | * key parameters. This ID can be used in checking whether a | ||
2094 | * certificate corresponds to the given private key. | ||
2095 | * | ||
2096 | * If the buffer provided is not long enough to hold the output, then | ||
2097 | * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will | ||
2098 | * be returned. The output will normally be a SHA-1 hash output, | ||
2099 | * which is 20 bytes. | ||
2100 | * | ||
2101 | * Return value: In case of failure a negative value will be | ||
2102 | * returned, and 0 on success. | ||
2103 | **/ | ||
2104 | int | ||
2105 | gnutls_x509_crt_get_key_id (gnutls_x509_crt_t crt, | ||
2106 | unsigned int flags, | ||
2107 | unsigned char *output_data, | ||
2108 | size_t * output_data_size) | ||
2109 | { | ||
2110 | int pk, result = 0; | ||
2111 | gnutls_datum_t pubkey; | ||
2112 | |||
2113 | if (crt == NULL) | ||
2114 | { | ||
2115 | gnutls_assert (); | ||
2116 | return GNUTLS_E_INVALID_REQUEST; | ||
2117 | } | ||
2118 | |||
2119 | if (*output_data_size < 20) | ||
2120 | { | ||
2121 | gnutls_assert (); | ||
2122 | *output_data_size = 20; | ||
2123 | return GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
2124 | } | ||
2125 | |||
2126 | pk = gnutls_x509_crt_get_pk_algorithm (crt, NULL); | ||
2127 | if (pk < 0) | ||
2128 | { | ||
2129 | gnutls_assert (); | ||
2130 | return pk; | ||
2131 | } | ||
2132 | |||
2133 | if (pk == GNUTLS_PK_RSA) | ||
2134 | { | ||
2135 | /* This is for compatibility with what GnuTLS has printed for | ||
2136 | RSA/DSA before the code below was added. The code below is | ||
2137 | applicable to all types, and it would probably be a better | ||
2138 | idea to use it for RSA/DSA too, but doing so would break | ||
2139 | backwards compatibility. */ | ||
2140 | return rsadsa_get_key_id (crt, pk, output_data, output_data_size); | ||
2141 | } | ||
2142 | |||
2143 | pubkey.size = 0; | ||
2144 | result = asn1_der_coding (crt->cert, "tbsCertificate.subjectPublicKeyInfo", | ||
2145 | NULL, &pubkey.size, NULL); | ||
2146 | if (result != ASN1_MEM_ERROR) | ||
2147 | { | ||
2148 | gnutls_assert (); | ||
2149 | return _gnutls_asn2err (result); | ||
2150 | } | ||
2151 | |||
2152 | pubkey.data = gnutls_alloca (pubkey.size); | ||
2153 | if (pubkey.data == NULL) | ||
2154 | { | ||
2155 | gnutls_assert (); | ||
2156 | return GNUTLS_E_MEMORY_ERROR; | ||
2157 | } | ||
2158 | |||
2159 | result = asn1_der_coding (crt->cert, "tbsCertificate.subjectPublicKeyInfo", | ||
2160 | pubkey.data, &pubkey.size, NULL); | ||
2161 | if (result != ASN1_SUCCESS) | ||
2162 | { | ||
2163 | gnutls_assert (); | ||
2164 | gnutls_afree (pubkey.data); | ||
2165 | return _gnutls_asn2err (result); | ||
2166 | } | ||
2167 | |||
2168 | result = gnutls_fingerprint (GNUTLS_DIG_SHA1, &pubkey, output_data, | ||
2169 | output_data_size); | ||
2170 | |||
2171 | gnutls_afree (pubkey.data); | ||
2172 | |||
2173 | return result; | ||
2174 | } | ||
2175 | |||
2176 | #ifdef ENABLE_PKI | ||
2177 | |||
2178 | /** | ||
2179 | * gnutls_x509_crt_check_revocation - This function checks if the given certificate is revoked | ||
2180 | * @cert: should contain a gnutls_x509_crt_t structure | ||
2181 | * @crl_list: should contain a list of gnutls_x509_crl_t structures | ||
2182 | * @crl_list_length: the length of the crl_list | ||
2183 | * | ||
2184 | * This function will return check if the given certificate is | ||
2185 | * revoked. It is assumed that the CRLs have been verified before. | ||
2186 | * | ||
2187 | * Returns: 0 if the certificate is NOT revoked, and 1 if it is. A | ||
2188 | * negative value is returned on error. | ||
2189 | **/ | ||
2190 | int | ||
2191 | gnutls_x509_crt_check_revocation (gnutls_x509_crt_t cert, | ||
2192 | const gnutls_x509_crl_t * crl_list, | ||
2193 | int crl_list_length) | ||
2194 | { | ||
2195 | opaque serial[64]; | ||
2196 | opaque cert_serial[64]; | ||
2197 | size_t serial_size, cert_serial_size; | ||
2198 | int ncerts, ret, i, j; | ||
2199 | gnutls_datum_t dn1, dn2; | ||
2200 | |||
2201 | if (cert == NULL) | ||
2202 | { | ||
2203 | gnutls_assert (); | ||
2204 | return GNUTLS_E_INVALID_REQUEST; | ||
2205 | } | ||
2206 | |||
2207 | for (j = 0; j < crl_list_length; j++) | ||
2208 | { /* do for all the crls */ | ||
2209 | |||
2210 | /* Step 1. check if issuer's DN match | ||
2211 | */ | ||
2212 | ret = _gnutls_x509_crl_get_raw_issuer_dn (crl_list[j], &dn1); | ||
2213 | if (ret < 0) | ||
2214 | { | ||
2215 | gnutls_assert (); | ||
2216 | return ret; | ||
2217 | } | ||
2218 | |||
2219 | ret = gnutls_x509_crt_get_raw_issuer_dn (cert, &dn2); | ||
2220 | if (ret < 0) | ||
2221 | { | ||
2222 | gnutls_assert (); | ||
2223 | return ret; | ||
2224 | } | ||
2225 | |||
2226 | ret = _gnutls_x509_compare_raw_dn (&dn1, &dn2); | ||
2227 | _gnutls_free_datum (&dn1); | ||
2228 | _gnutls_free_datum (&dn2); | ||
2229 | if (ret == 0) | ||
2230 | { | ||
2231 | /* issuers do not match so don't even | ||
2232 | * bother checking. | ||
2233 | */ | ||
2234 | continue; | ||
2235 | } | ||
2236 | |||
2237 | /* Step 2. Read the certificate's serial number | ||
2238 | */ | ||
2239 | cert_serial_size = sizeof (cert_serial); | ||
2240 | ret = gnutls_x509_crt_get_serial (cert, cert_serial, &cert_serial_size); | ||
2241 | if (ret < 0) | ||
2242 | { | ||
2243 | gnutls_assert (); | ||
2244 | return ret; | ||
2245 | } | ||
2246 | |||
2247 | /* Step 3. cycle through the CRL serials and compare with | ||
2248 | * certificate serial we have. | ||
2249 | */ | ||
2250 | |||
2251 | ncerts = gnutls_x509_crl_get_crt_count (crl_list[j]); | ||
2252 | if (ncerts < 0) | ||
2253 | { | ||
2254 | gnutls_assert (); | ||
2255 | return ncerts; | ||
2256 | } | ||
2257 | |||
2258 | for (i = 0; i < ncerts; i++) | ||
2259 | { | ||
2260 | serial_size = sizeof (serial); | ||
2261 | ret = gnutls_x509_crl_get_crt_serial (crl_list[j], i, serial, | ||
2262 | &serial_size, NULL); | ||
2263 | |||
2264 | if (ret < 0) | ||
2265 | { | ||
2266 | gnutls_assert (); | ||
2267 | return ret; | ||
2268 | } | ||
2269 | |||
2270 | if (serial_size == cert_serial_size) | ||
2271 | { | ||
2272 | if (memcmp (serial, cert_serial, serial_size) == 0) | ||
2273 | { | ||
2274 | /* serials match */ | ||
2275 | return 1; /* revoked! */ | ||
2276 | } | ||
2277 | } | ||
2278 | } | ||
2279 | |||
2280 | } | ||
2281 | return 0; /* not revoked. */ | ||
2282 | } | ||
2283 | |||
2284 | /** | ||
2285 | * gnutls_x509_crt_verify_data - This function will verify the given signed data. | ||
2286 | * @crt: Holds the certificate | ||
2287 | * @flags: should be 0 for now | ||
2288 | * @data: holds the data to be signed | ||
2289 | * @signature: contains the signature | ||
2290 | * | ||
2291 | * This function will verify the given signed data, using the | ||
2292 | * parameters from the certificate. | ||
2293 | * | ||
2294 | * Returns: In case of a verification failure 0 is returned, and 1 on | ||
2295 | * success. | ||
2296 | **/ | ||
2297 | int | ||
2298 | gnutls_x509_crt_verify_data (gnutls_x509_crt_t crt, | ||
2299 | unsigned int flags, | ||
2300 | const gnutls_datum_t * data, | ||
2301 | const gnutls_datum_t * signature) | ||
2302 | { | ||
2303 | int result; | ||
2304 | |||
2305 | if (crt == NULL) | ||
2306 | { | ||
2307 | gnutls_assert (); | ||
2308 | return GNUTLS_E_INVALID_REQUEST; | ||
2309 | } | ||
2310 | |||
2311 | result = _gnutls_x509_verify_signature (data, signature, crt); | ||
2312 | if (result < 0) | ||
2313 | { | ||
2314 | gnutls_assert (); | ||
2315 | return 0; | ||
2316 | } | ||
2317 | |||
2318 | return result; | ||
2319 | } | ||
2320 | |||
2321 | /** | ||
2322 | * gnutls_x509_crt_get_crl_dist_points - This function returns the CRL distribution points | ||
2323 | * @cert: should contain a gnutls_x509_crt_t structure | ||
2324 | * @seq: specifies the sequence number of the distribution point (0 for the first one, 1 for the second etc.) | ||
2325 | * @ret: is the place where the distribution point will be copied to | ||
2326 | * @ret_size: holds the size of ret. | ||
2327 | * @reason_flags: Revocation reasons flags. | ||
2328 | * @critical: will be non zero if the extension is marked as critical (may be null) | ||
2329 | * | ||
2330 | * This function will return the CRL distribution points (2.5.29.31), | ||
2331 | * contained in the given certificate. | ||
2332 | * | ||
2333 | * @reason_flags should be an ORed sequence of | ||
2334 | * GNUTLS_CRL_REASON_UNUSED, GNUTLS_CRL_REASON_KEY_COMPROMISE, | ||
2335 | * GNUTLS_CRL_REASON_CA_COMPROMISE, | ||
2336 | * GNUTLS_CRL_REASON_AFFILIATION_CHANGED, | ||
2337 | * GNUTLS_CRL_REASON_SUPERSEEDED, | ||
2338 | * GNUTLS_CRL_REASON_CESSATION_OF_OPERATION, | ||
2339 | * GNUTLS_CRL_REASON_CERTIFICATE_HOLD, | ||
2340 | * GNUTLS_CRL_REASON_PRIVILEGE_WITHDRAWN, | ||
2341 | * GNUTLS_CRL_REASON_AA_COMPROMISE, or zero for all possible reasons. | ||
2342 | * | ||
2343 | * This is specified in X509v3 Certificate Extensions. GNUTLS will | ||
2344 | * return the distribution point type, or a negative error code on | ||
2345 | * error. | ||
2346 | * | ||
2347 | * Returns %GNUTLS_E_SHORT_MEMORY_BUFFER and updates &@ret_size if | ||
2348 | * &@ret_size is not enough to hold the distribution point, or the | ||
2349 | * type of the distribution point if everything was ok. The type is | ||
2350 | * one of the enumerated %gnutls_x509_subject_alt_name_t. If the | ||
2351 | * certificate does not have an Alternative name with the specified | ||
2352 | * sequence number then %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is | ||
2353 | * returned. | ||
2354 | **/ | ||
2355 | int | ||
2356 | gnutls_x509_crt_get_crl_dist_points (gnutls_x509_crt_t cert, | ||
2357 | unsigned int seq, | ||
2358 | void *ret, | ||
2359 | size_t * ret_size, | ||
2360 | unsigned int *reason_flags, | ||
2361 | unsigned int *critical) | ||
2362 | { | ||
2363 | int result; | ||
2364 | gnutls_datum_t dist_points = { NULL, | ||
2365 | 0 | ||
2366 | }; | ||
2367 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
2368 | char name[MAX_NAME_SIZE]; | ||
2369 | int len; | ||
2370 | gnutls_x509_subject_alt_name_t type; | ||
2371 | uint8_t reasons[2]; | ||
2372 | |||
2373 | if (cert == NULL) | ||
2374 | { | ||
2375 | gnutls_assert (); | ||
2376 | return GNUTLS_E_INVALID_REQUEST; | ||
2377 | } | ||
2378 | |||
2379 | if (*ret_size > 0 && ret) | ||
2380 | memset (ret, 0, *ret_size); | ||
2381 | else | ||
2382 | *ret_size = 0; | ||
2383 | |||
2384 | if (reason_flags) | ||
2385 | *reason_flags = 0; | ||
2386 | |||
2387 | result = _gnutls_x509_crt_get_extension (cert, "2.5.29.31", 0, &dist_points, | ||
2388 | critical); | ||
2389 | if (result < 0) | ||
2390 | { | ||
2391 | return result; | ||
2392 | } | ||
2393 | |||
2394 | if (dist_points.size == 0 || dist_points.data == NULL) | ||
2395 | { | ||
2396 | gnutls_assert (); | ||
2397 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
2398 | } | ||
2399 | |||
2400 | result = | ||
2401 | asn1_create_element (_gnutls_get_pkix (), "PKIX1.CRLDistributionPoints", | ||
2402 | &c2); | ||
2403 | if (result != ASN1_SUCCESS) | ||
2404 | { | ||
2405 | gnutls_assert (); | ||
2406 | _gnutls_free_datum (&dist_points); | ||
2407 | return _gnutls_asn2err (result); | ||
2408 | } | ||
2409 | |||
2410 | result = asn1_der_decoding (&c2, dist_points.data, dist_points.size, NULL); | ||
2411 | _gnutls_free_datum (&dist_points); | ||
2412 | |||
2413 | if (result != ASN1_SUCCESS) | ||
2414 | { | ||
2415 | gnutls_assert (); | ||
2416 | asn1_delete_structure (&c2); | ||
2417 | return _gnutls_asn2err (result); | ||
2418 | } | ||
2419 | |||
2420 | /* Return the different names from the first CRLDistr. point. | ||
2421 | * The whole thing is a mess. | ||
2422 | */ | ||
2423 | _gnutls_str_cpy (name, sizeof (name), "?1.distributionPoint.fullName"); | ||
2424 | |||
2425 | result = parse_general_name (c2, name, seq, ret, ret_size, NULL, 0); | ||
2426 | if (result < 0) | ||
2427 | { | ||
2428 | asn1_delete_structure (&c2); | ||
2429 | return result; | ||
2430 | } | ||
2431 | |||
2432 | type = result; | ||
2433 | |||
2434 | /* Read the CRL reasons. | ||
2435 | */ | ||
2436 | if (reason_flags) | ||
2437 | { | ||
2438 | _gnutls_str_cpy (name, sizeof (name), "?1.reasons"); | ||
2439 | |||
2440 | reasons[0] = reasons[1] = 0; | ||
2441 | |||
2442 | len = sizeof (reasons); | ||
2443 | result = asn1_read_value (c2, name, reasons, &len); | ||
2444 | |||
2445 | if (result != ASN1_VALUE_NOT_FOUND && result != ASN1_SUCCESS) | ||
2446 | { | ||
2447 | gnutls_assert (); | ||
2448 | asn1_delete_structure (&c2); | ||
2449 | return _gnutls_asn2err (result); | ||
2450 | } | ||
2451 | |||
2452 | *reason_flags = reasons[0] | (reasons[1] << 8); | ||
2453 | } | ||
2454 | |||
2455 | return type; | ||
2456 | } | ||
2457 | |||
2458 | /** | ||
2459 | * gnutls_x509_crt_get_key_purpose_oid - This function returns the Certificate's key purpose OIDs | ||
2460 | * @cert: should contain a gnutls_x509_crt_t structure | ||
2461 | * @indx: This specifies which OID to return. Use zero to get the first one. | ||
2462 | * @oid: a pointer to a buffer to hold the OID (may be null) | ||
2463 | * @sizeof_oid: initially holds the size of @oid | ||
2464 | * | ||
2465 | * This function will extract the key purpose OIDs of the Certificate | ||
2466 | * specified by the given index. These are stored in the Extended Key | ||
2467 | * Usage extension (2.5.29.37) See the GNUTLS_KP_* definitions for | ||
2468 | * human readable names. | ||
2469 | * | ||
2470 | * If @oid is null then only the size will be filled. | ||
2471 | * | ||
2472 | * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is | ||
2473 | * not long enough, and in that case the *sizeof_oid will be updated | ||
2474 | * with the required size. On success 0 is returned. | ||
2475 | **/ | ||
2476 | int | ||
2477 | gnutls_x509_crt_get_key_purpose_oid (gnutls_x509_crt_t cert, | ||
2478 | int indx, | ||
2479 | void *oid, | ||
2480 | size_t * sizeof_oid, | ||
2481 | unsigned int *critical) | ||
2482 | { | ||
2483 | char tmpstr[MAX_NAME_SIZE]; | ||
2484 | int result, len; | ||
2485 | gnutls_datum_t id; | ||
2486 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
2487 | |||
2488 | if (cert == NULL) | ||
2489 | { | ||
2490 | gnutls_assert (); | ||
2491 | return GNUTLS_E_INVALID_REQUEST; | ||
2492 | } | ||
2493 | |||
2494 | if (oid) | ||
2495 | memset (oid, 0, *sizeof_oid); | ||
2496 | else | ||
2497 | *sizeof_oid = 0; | ||
2498 | |||
2499 | if ((result = _gnutls_x509_crt_get_extension (cert, "2.5.29.37", 0, &id, | ||
2500 | critical)) < 0) | ||
2501 | { | ||
2502 | return result; | ||
2503 | } | ||
2504 | |||
2505 | if (id.size == 0 || id.data == NULL) | ||
2506 | { | ||
2507 | gnutls_assert (); | ||
2508 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
2509 | } | ||
2510 | |||
2511 | result = | ||
2512 | asn1_create_element (_gnutls_get_pkix (), "PKIX1.ExtKeyUsageSyntax", &c2); | ||
2513 | if (result != ASN1_SUCCESS) | ||
2514 | { | ||
2515 | gnutls_assert (); | ||
2516 | _gnutls_free_datum (&id); | ||
2517 | return _gnutls_asn2err (result); | ||
2518 | } | ||
2519 | |||
2520 | result = asn1_der_decoding (&c2, id.data, id.size, NULL); | ||
2521 | _gnutls_free_datum (&id); | ||
2522 | |||
2523 | if (result != ASN1_SUCCESS) | ||
2524 | { | ||
2525 | gnutls_assert (); | ||
2526 | asn1_delete_structure (&c2); | ||
2527 | return _gnutls_asn2err (result); | ||
2528 | } | ||
2529 | |||
2530 | indx++; | ||
2531 | /* create a string like "?1" | ||
2532 | */ | ||
2533 | snprintf (tmpstr, sizeof (tmpstr), "?%u", indx); | ||
2534 | |||
2535 | len = *sizeof_oid; | ||
2536 | result = asn1_read_value (c2, tmpstr, oid, &len); | ||
2537 | |||
2538 | *sizeof_oid = len; | ||
2539 | asn1_delete_structure (&c2); | ||
2540 | |||
2541 | if (result == ASN1_VALUE_NOT_FOUND || result == ASN1_ELEMENT_NOT_FOUND) | ||
2542 | { | ||
2543 | return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; | ||
2544 | } | ||
2545 | |||
2546 | if (result != ASN1_SUCCESS) | ||
2547 | { | ||
2548 | gnutls_assert (); | ||
2549 | return _gnutls_asn2err (result); | ||
2550 | } | ||
2551 | |||
2552 | return 0; | ||
2553 | |||
2554 | } | ||
2555 | |||
2556 | /** | ||
2557 | * gnutls_x509_crt_get_pk_rsa_raw - This function will export the RSA public key | ||
2558 | * @crt: Holds the certificate | ||
2559 | * @m: will hold the modulus | ||
2560 | * @e: will hold the public exponent | ||
2561 | * | ||
2562 | * This function will export the RSA public key's parameters found in | ||
2563 | * the given structure. The new parameters will be allocated using | ||
2564 | * gnutls_malloc() and will be stored in the appropriate datum. | ||
2565 | * | ||
2566 | * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error. | ||
2567 | **/ | ||
2568 | int | ||
2569 | gnutls_x509_crt_get_pk_rsa_raw (gnutls_x509_crt_t crt, | ||
2570 | gnutls_datum_t * m, gnutls_datum_t * e) | ||
2571 | { | ||
2572 | int ret; | ||
2573 | mpi_t params[MAX_PUBLIC_PARAMS_SIZE]; | ||
2574 | int params_size = MAX_PUBLIC_PARAMS_SIZE; | ||
2575 | int i; | ||
2576 | |||
2577 | if (crt == NULL) | ||
2578 | { | ||
2579 | gnutls_assert (); | ||
2580 | return GNUTLS_E_INVALID_REQUEST; | ||
2581 | } | ||
2582 | |||
2583 | ret = gnutls_x509_crt_get_pk_algorithm (crt, NULL); | ||
2584 | if (ret != GNUTLS_PK_RSA) | ||
2585 | { | ||
2586 | gnutls_assert (); | ||
2587 | return GNUTLS_E_INVALID_REQUEST; | ||
2588 | } | ||
2589 | |||
2590 | ret = _gnutls_x509_crt_get_mpis (crt, params, ¶ms_size); | ||
2591 | if (ret < 0) | ||
2592 | { | ||
2593 | gnutls_assert (); | ||
2594 | return ret; | ||
2595 | } | ||
2596 | |||
2597 | ret = _gnutls_mpi_dprint (m, params[0]); | ||
2598 | if (ret < 0) | ||
2599 | { | ||
2600 | gnutls_assert (); | ||
2601 | goto cleanup; | ||
2602 | } | ||
2603 | |||
2604 | ret = _gnutls_mpi_dprint (e, params[1]); | ||
2605 | if (ret < 0) | ||
2606 | { | ||
2607 | gnutls_assert (); | ||
2608 | _gnutls_free_datum (m); | ||
2609 | goto cleanup; | ||
2610 | } | ||
2611 | |||
2612 | ret = 0; | ||
2613 | |||
2614 | cleanup:for (i = 0; i < params_size; i++) | ||
2615 | { | ||
2616 | _gnutls_mpi_release (¶ms[i]); | ||
2617 | } | ||
2618 | return ret; | ||
2619 | } | ||
2620 | |||
2621 | /** | ||
2622 | * gnutls_x509_crt_get_pk_dsa_raw - This function will export the DSA public key | ||
2623 | * @crt: Holds the certificate | ||
2624 | * @p: will hold the p | ||
2625 | * @q: will hold the q | ||
2626 | * @g: will hold the g | ||
2627 | * @y: will hold the y | ||
2628 | * | ||
2629 | * This function will export the DSA public key's parameters found in | ||
2630 | * the given certificate. The new parameters will be allocated using | ||
2631 | * gnutls_malloc() and will be stored in the appropriate datum. | ||
2632 | * | ||
2633 | * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error. | ||
2634 | **/ | ||
2635 | int | ||
2636 | gnutls_x509_crt_get_pk_dsa_raw (gnutls_x509_crt_t crt, | ||
2637 | gnutls_datum_t * p, | ||
2638 | gnutls_datum_t * q, | ||
2639 | gnutls_datum_t * g, gnutls_datum_t * y) | ||
2640 | { | ||
2641 | int ret; | ||
2642 | mpi_t params[MAX_PUBLIC_PARAMS_SIZE]; | ||
2643 | int params_size = MAX_PUBLIC_PARAMS_SIZE; | ||
2644 | int i; | ||
2645 | |||
2646 | if (crt == NULL) | ||
2647 | { | ||
2648 | gnutls_assert (); | ||
2649 | return GNUTLS_E_INVALID_REQUEST; | ||
2650 | } | ||
2651 | |||
2652 | ret = gnutls_x509_crt_get_pk_algorithm (crt, NULL); | ||
2653 | |||
2654 | ret = _gnutls_x509_crt_get_mpis (crt, params, ¶ms_size); | ||
2655 | if (ret < 0) | ||
2656 | { | ||
2657 | gnutls_assert (); | ||
2658 | return ret; | ||
2659 | } | ||
2660 | |||
2661 | /* P */ | ||
2662 | ret = _gnutls_mpi_dprint (p, params[0]); | ||
2663 | if (ret < 0) | ||
2664 | { | ||
2665 | gnutls_assert (); | ||
2666 | goto cleanup; | ||
2667 | } | ||
2668 | |||
2669 | /* Q */ | ||
2670 | ret = _gnutls_mpi_dprint (q, params[1]); | ||
2671 | if (ret < 0) | ||
2672 | { | ||
2673 | gnutls_assert (); | ||
2674 | _gnutls_free_datum (p); | ||
2675 | goto cleanup; | ||
2676 | } | ||
2677 | |||
2678 | /* G */ | ||
2679 | ret = _gnutls_mpi_dprint (g, params[2]); | ||
2680 | if (ret < 0) | ||
2681 | { | ||
2682 | gnutls_assert (); | ||
2683 | _gnutls_free_datum (p); | ||
2684 | _gnutls_free_datum (q); | ||
2685 | goto cleanup; | ||
2686 | } | ||
2687 | |||
2688 | /* Y */ | ||
2689 | ret = _gnutls_mpi_dprint (y, params[3]); | ||
2690 | if (ret < 0) | ||
2691 | { | ||
2692 | gnutls_assert (); | ||
2693 | _gnutls_free_datum (p); | ||
2694 | _gnutls_free_datum (g); | ||
2695 | _gnutls_free_datum (q); | ||
2696 | goto cleanup; | ||
2697 | } | ||
2698 | |||
2699 | ret = 0; | ||
2700 | |||
2701 | cleanup:for (i = 0; i < params_size; i++) | ||
2702 | { | ||
2703 | _gnutls_mpi_release (¶ms[i]); | ||
2704 | } | ||
2705 | return ret; | ||
2706 | |||
2707 | } | ||
2708 | |||
2709 | #endif | ||
2710 | |||
2711 | /** | ||
2712 | * gnutls_x509_crt_list_import - This function will import a PEM encoded certificate list | ||
2713 | * @certs: The structures to store the parsed certificate. Must not be initialized. | ||
2714 | * @cert_max: Initially must hold the maximum number of certs. It will be updated with the number of certs available. | ||
2715 | * @data: The PEM encoded certificate. | ||
2716 | * @format: One of DER or PEM. | ||
2717 | * @flags: must be zero or an OR'd sequence of gnutls_certificate_import_flags. | ||
2718 | * | ||
2719 | * This function will convert the given PEM encoded certificate list | ||
2720 | * to the native gnutls_x509_crt_t format. The output will be stored | ||
2721 | * in @certs. They will be automatically initialized. | ||
2722 | * | ||
2723 | * If the Certificate is PEM encoded it should have a header of "X509 | ||
2724 | * CERTIFICATE", or "CERTIFICATE". | ||
2725 | * | ||
2726 | * Returns: the number of certificates read or a negative error value. | ||
2727 | **/ | ||
2728 | int | ||
2729 | gnutls_x509_crt_list_import (gnutls_x509_crt_t * certs, | ||
2730 | unsigned int *cert_max, | ||
2731 | const gnutls_datum_t * data, | ||
2732 | gnutls_x509_crt_fmt_t format, unsigned int flags) | ||
2733 | { | ||
2734 | int size; | ||
2735 | const char *ptr; | ||
2736 | gnutls_datum_t tmp; | ||
2737 | int ret, nocopy = 0; | ||
2738 | unsigned int count = 0, j; | ||
2739 | |||
2740 | if (format == GNUTLS_X509_FMT_DER) | ||
2741 | { | ||
2742 | if (*cert_max < 1) | ||
2743 | { | ||
2744 | *cert_max = 1; | ||
2745 | return GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
2746 | } | ||
2747 | |||
2748 | count = 1; /* import only the first one */ | ||
2749 | |||
2750 | ret = gnutls_x509_crt_init (&certs[0]); | ||
2751 | if (ret < 0) | ||
2752 | { | ||
2753 | gnutls_assert (); | ||
2754 | goto error; | ||
2755 | } | ||
2756 | |||
2757 | ret = gnutls_x509_crt_import (certs[0], data, format); | ||
2758 | if (ret < 0) | ||
2759 | { | ||
2760 | gnutls_assert (); | ||
2761 | goto error; | ||
2762 | } | ||
2763 | |||
2764 | *cert_max = 1; | ||
2765 | return 1; | ||
2766 | } | ||
2767 | |||
2768 | /* move to the certificate | ||
2769 | */ | ||
2770 | ptr = memmem (data->data, data->size, | ||
2771 | PEM_CERT_SEP, sizeof (PEM_CERT_SEP) - 1); | ||
2772 | if (ptr == NULL) | ||
2773 | ptr = memmem (data->data, data->size, | ||
2774 | PEM_CERT_SEP2, sizeof (PEM_CERT_SEP2) - 1); | ||
2775 | |||
2776 | if (ptr == NULL) | ||
2777 | { | ||
2778 | gnutls_assert (); | ||
2779 | return GNUTLS_E_BASE64_DECODING_ERROR; | ||
2780 | } | ||
2781 | size = data->size - (ptr - (char *) data->data); | ||
2782 | |||
2783 | count = 0; | ||
2784 | |||
2785 | do | ||
2786 | { | ||
2787 | if (count >= *cert_max) | ||
2788 | { | ||
2789 | if (!(flags & GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED)) | ||
2790 | break; | ||
2791 | else | ||
2792 | nocopy = 1; | ||
2793 | } | ||
2794 | |||
2795 | if (!nocopy) | ||
2796 | { | ||
2797 | ret = gnutls_x509_crt_init (&certs[count]); | ||
2798 | if (ret < 0) | ||
2799 | { | ||
2800 | gnutls_assert (); | ||
2801 | goto error; | ||
2802 | } | ||
2803 | |||
2804 | tmp.data = (void *) ptr; | ||
2805 | tmp.size = size; | ||
2806 | |||
2807 | ret = | ||
2808 | gnutls_x509_crt_import (certs[count], &tmp, GNUTLS_X509_FMT_PEM); | ||
2809 | if (ret < 0) | ||
2810 | { | ||
2811 | gnutls_assert (); | ||
2812 | goto error; | ||
2813 | } | ||
2814 | } | ||
2815 | |||
2816 | /* now we move ptr after the pem header | ||
2817 | */ | ||
2818 | ptr++; | ||
2819 | /* find the next certificate (if any) | ||
2820 | */ | ||
2821 | size = data->size - (ptr - (char *) data->data); | ||
2822 | |||
2823 | if (size > 0) | ||
2824 | { | ||
2825 | char *ptr2; | ||
2826 | |||
2827 | ptr2 = memmem (ptr, size, PEM_CERT_SEP, sizeof (PEM_CERT_SEP) - 1); | ||
2828 | if (ptr2 == NULL) | ||
2829 | ptr2 = | ||
2830 | memmem (ptr, size, PEM_CERT_SEP2, sizeof (PEM_CERT_SEP2) - 1); | ||
2831 | |||
2832 | ptr = ptr2; | ||
2833 | } | ||
2834 | else | ||
2835 | ptr = NULL; | ||
2836 | |||
2837 | count++; | ||
2838 | } | ||
2839 | while (ptr != NULL); | ||
2840 | |||
2841 | *cert_max = count; | ||
2842 | |||
2843 | if (nocopy == 0) | ||
2844 | return count; | ||
2845 | else | ||
2846 | return GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
2847 | |||
2848 | error:for (j = 0; j < count; j++) | ||
2849 | gnutls_x509_crt_deinit (certs[j]); | ||
2850 | return ret; | ||
2851 | } | ||
diff --git a/src/daemon/https/x509/x509.h b/src/daemon/https/x509/x509.h new file mode 100644 index 00000000..c9bb22ef --- /dev/null +++ b/src/daemon/https/x509/x509.h | |||
@@ -0,0 +1,928 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef X509_H | ||
26 | # define X509_H | ||
27 | |||
28 | #define MIN(X,Y) ((X) > (Y) ? (Y) : (X)); | ||
29 | |||
30 | #ifdef __cplusplus | ||
31 | extern "C" | ||
32 | { | ||
33 | #endif | ||
34 | |||
35 | #include <gnutls.h> | ||
36 | // TODO #include "libtasn1.h" | ||
37 | #include "gnutls_mpi.h" | ||
38 | |||
39 | /* Some OIDs usually found in Distinguished names, or | ||
40 | * in Subject Directory Attribute extensions. | ||
41 | */ | ||
42 | #define GNUTLS_OID_X520_COUNTRY_NAME "2.5.4.6" | ||
43 | #define GNUTLS_OID_X520_ORGANIZATION_NAME "2.5.4.10" | ||
44 | #define GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME "2.5.4.11" | ||
45 | #define GNUTLS_OID_X520_COMMON_NAME "2.5.4.3" | ||
46 | #define GNUTLS_OID_X520_LOCALITY_NAME "2.5.4.7" | ||
47 | #define GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME "2.5.4.8" | ||
48 | |||
49 | #define GNUTLS_OID_X520_INITIALS "2.5.4.43" | ||
50 | #define GNUTLS_OID_X520_GENERATION_QUALIFIER "2.5.4.44" | ||
51 | #define GNUTLS_OID_X520_SURNAME "2.5.4.4" | ||
52 | #define GNUTLS_OID_X520_GIVEN_NAME "2.5.4.42" | ||
53 | #define GNUTLS_OID_X520_TITLE "2.5.4.12" | ||
54 | #define GNUTLS_OID_X520_DN_QUALIFIER "2.5.4.46" | ||
55 | #define GNUTLS_OID_X520_PSEUDONYM "2.5.4.65" | ||
56 | |||
57 | #define GNUTLS_OID_LDAP_DC "0.9.2342.19200300.100.1.25" | ||
58 | #define GNUTLS_OID_LDAP_UID "0.9.2342.19200300.100.1.1" | ||
59 | |||
60 | /* The following should not be included in DN. | ||
61 | */ | ||
62 | #define GNUTLS_OID_PKCS9_EMAIL "1.2.840.113549.1.9.1" | ||
63 | |||
64 | #define GNUTLS_OID_PKIX_DATE_OF_BIRTH "1.3.6.1.5.5.7.9.1" | ||
65 | #define GNUTLS_OID_PKIX_PLACE_OF_BIRTH "1.3.6.1.5.5.7.9.2" | ||
66 | #define GNUTLS_OID_PKIX_GENDER "1.3.6.1.5.5.7.9.3" | ||
67 | #define GNUTLS_OID_PKIX_COUNTRY_OF_CITIZENSHIP "1.3.6.1.5.5.7.9.4" | ||
68 | #define GNUTLS_OID_PKIX_COUNTRY_OF_RESIDENCE "1.3.6.1.5.5.7.9.5" | ||
69 | |||
70 | /* Key purpose Object Identifiers. | ||
71 | */ | ||
72 | #define GNUTLS_KP_TLS_WWW_SERVER "1.3.6.1.5.5.7.3.1" | ||
73 | #define GNUTLS_KP_TLS_WWW_CLIENT "1.3.6.1.5.5.7.3.2" | ||
74 | #define GNUTLS_KP_CODE_SIGNING "1.3.6.1.5.5.7.3.3" | ||
75 | #define GNUTLS_KP_EMAIL_PROTECTION "1.3.6.1.5.5.7.3.4" | ||
76 | #define GNUTLS_KP_TIME_STAMPING "1.3.6.1.5.5.7.3.8" | ||
77 | #define GNUTLS_KP_OCSP_SIGNING "1.3.6.1.5.5.7.3.9" | ||
78 | #define GNUTLS_KP_ANY "2.5.29.37.0" | ||
79 | |||
80 | /* Certificate handling functions. | ||
81 | */ | ||
82 | typedef enum gnutls_certificate_import_flags | ||
83 | { | ||
84 | /* Fail if the certificates in the buffer are more than the space | ||
85 | * allocated for certificates. The error code will be | ||
86 | * GNUTLS_E_SHORT_MEMORY_BUFFER. | ||
87 | */ | ||
88 | GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED = 1 | ||
89 | } gnutls_certificate_import_flags; | ||
90 | |||
91 | int gnutls_x509_crt_init(gnutls_x509_crt_t * cert); | ||
92 | void gnutls_x509_crt_deinit(gnutls_x509_crt_t cert); | ||
93 | int gnutls_x509_crt_import(gnutls_x509_crt_t cert, | ||
94 | const gnutls_datum_t * data, | ||
95 | gnutls_x509_crt_fmt_t format); | ||
96 | int gnutls_x509_crt_list_import(gnutls_x509_crt_t * certs, | ||
97 | unsigned int *cert_max, | ||
98 | const gnutls_datum_t * data, | ||
99 | gnutls_x509_crt_fmt_t format, | ||
100 | unsigned int flags); | ||
101 | int gnutls_x509_crt_export(gnutls_x509_crt_t cert, | ||
102 | gnutls_x509_crt_fmt_t format, | ||
103 | void *output_data, | ||
104 | size_t * output_data_size); | ||
105 | int gnutls_x509_crt_get_issuer_dn(gnutls_x509_crt_t cert, | ||
106 | char *buf, | ||
107 | size_t * sizeof_buf); | ||
108 | int gnutls_x509_crt_get_issuer_dn_oid(gnutls_x509_crt_t cert, | ||
109 | int indx, | ||
110 | void *oid, | ||
111 | size_t * sizeof_oid); | ||
112 | int gnutls_x509_crt_get_issuer_dn_by_oid(gnutls_x509_crt_t cert, | ||
113 | const char *oid, | ||
114 | int indx, | ||
115 | unsigned int raw_flag, | ||
116 | void *buf, | ||
117 | size_t * sizeof_buf); | ||
118 | int gnutls_x509_crt_get_dn(gnutls_x509_crt_t cert, | ||
119 | char *buf, | ||
120 | size_t * sizeof_buf); | ||
121 | int gnutls_x509_crt_get_dn_oid(gnutls_x509_crt_t cert, | ||
122 | int indx, | ||
123 | void *oid, | ||
124 | size_t * sizeof_oid); | ||
125 | int gnutls_x509_crt_get_dn_by_oid(gnutls_x509_crt_t cert, | ||
126 | const char *oid, | ||
127 | int indx, | ||
128 | unsigned int raw_flag, | ||
129 | void *buf, | ||
130 | size_t * sizeof_buf); | ||
131 | int gnutls_x509_crt_check_hostname(gnutls_x509_crt_t cert, | ||
132 | const char *hostname); | ||
133 | |||
134 | int gnutls_x509_crt_get_signature_algorithm(gnutls_x509_crt_t cert); | ||
135 | int gnutls_x509_crt_get_signature(gnutls_x509_crt_t cert, | ||
136 | char *sig, | ||
137 | size_t *sizeof_sig); | ||
138 | int gnutls_x509_crt_get_version(gnutls_x509_crt_t cert); | ||
139 | int gnutls_x509_crt_get_key_id(gnutls_x509_crt_t crt, | ||
140 | unsigned int flags, | ||
141 | unsigned char *output_data, | ||
142 | size_t * output_data_size); | ||
143 | |||
144 | int gnutls_x509_crt_set_authority_key_id(gnutls_x509_crt_t cert, | ||
145 | const void *id, | ||
146 | size_t id_size); | ||
147 | int gnutls_x509_crt_get_authority_key_id(gnutls_x509_crt_t cert, | ||
148 | void *ret, | ||
149 | size_t * ret_size, | ||
150 | unsigned int *critical); | ||
151 | |||
152 | int gnutls_x509_crt_get_subject_key_id(gnutls_x509_crt_t cert, | ||
153 | void *ret, | ||
154 | size_t * ret_size, | ||
155 | unsigned int *critical); | ||
156 | |||
157 | #define GNUTLS_CRL_REASON_UNUSED 128 | ||
158 | #define GNUTLS_CRL_REASON_KEY_COMPROMISE 64 | ||
159 | #define GNUTLS_CRL_REASON_CA_COMPROMISE 32 | ||
160 | #define GNUTLS_CRL_REASON_AFFILIATION_CHANGED 16 | ||
161 | #define GNUTLS_CRL_REASON_SUPERSEEDED 8 | ||
162 | #define GNUTLS_CRL_REASON_CESSATION_OF_OPERATION 4 | ||
163 | #define GNUTLS_CRL_REASON_CERTIFICATE_HOLD 2 | ||
164 | #define GNUTLS_CRL_REASON_PRIVILEGE_WITHDRAWN 1 | ||
165 | #define GNUTLS_CRL_REASON_AA_COMPROMISE 32768 | ||
166 | |||
167 | int gnutls_x509_crt_get_crl_dist_points(gnutls_x509_crt_t cert, | ||
168 | unsigned int seq, | ||
169 | void *ret, | ||
170 | size_t * ret_size, | ||
171 | unsigned int *reason_flags, | ||
172 | unsigned int *critical); | ||
173 | int gnutls_x509_crt_set_crl_dist_points(gnutls_x509_crt_t crt, | ||
174 | gnutls_x509_subject_alt_name_t | ||
175 | type, | ||
176 | const void *data_string, | ||
177 | unsigned int reason_flags); | ||
178 | int gnutls_x509_crt_cpy_crl_dist_points(gnutls_x509_crt_t dst, | ||
179 | gnutls_x509_crt_t src); | ||
180 | |||
181 | time_t gnutls_x509_crt_get_activation_time(gnutls_x509_crt_t cert); | ||
182 | time_t gnutls_x509_crt_get_expiration_time(gnutls_x509_crt_t cert); | ||
183 | int gnutls_x509_crt_get_serial(gnutls_x509_crt_t cert, | ||
184 | void *result, | ||
185 | size_t * result_size); | ||
186 | |||
187 | int gnutls_x509_crt_get_pk_algorithm(gnutls_x509_crt_t cert, | ||
188 | unsigned int *bits); | ||
189 | int gnutls_x509_crt_get_pk_rsa_raw(gnutls_x509_crt_t crt, | ||
190 | gnutls_datum_t * m, | ||
191 | gnutls_datum_t * e); | ||
192 | int gnutls_x509_crt_get_pk_dsa_raw(gnutls_x509_crt_t crt, | ||
193 | gnutls_datum_t * p, | ||
194 | gnutls_datum_t * q, | ||
195 | gnutls_datum_t * g, | ||
196 | gnutls_datum_t * y); | ||
197 | |||
198 | int gnutls_x509_crt_get_subject_alt_name(gnutls_x509_crt_t cert, | ||
199 | unsigned int seq, | ||
200 | void *ret, | ||
201 | size_t * ret_size, | ||
202 | unsigned int *critical); | ||
203 | int gnutls_x509_crt_get_subject_alt_name2(gnutls_x509_crt_t cert, | ||
204 | unsigned int seq, | ||
205 | void *ret, | ||
206 | size_t * ret_size, | ||
207 | unsigned int* ret_type, | ||
208 | unsigned int *critical); | ||
209 | |||
210 | int gnutls_x509_crt_get_subject_alt_othername_oid(gnutls_x509_crt_t cert, | ||
211 | unsigned int seq, | ||
212 | void *ret, | ||
213 | size_t * ret_size); | ||
214 | |||
215 | int gnutls_x509_crt_get_ca_status(gnutls_x509_crt_t cert, | ||
216 | unsigned int *critical); | ||
217 | int gnutls_x509_crt_get_basic_constraints(gnutls_x509_crt_t cert, | ||
218 | unsigned int *critical, | ||
219 | int *ca, | ||
220 | int *pathlen); | ||
221 | |||
222 | /* The key_usage flags are defined in gnutls.h. They are the | ||
223 | * GNUTLS_KEY_* definitions. | ||
224 | */ | ||
225 | int gnutls_x509_crt_get_key_usage(gnutls_x509_crt_t cert, | ||
226 | unsigned int *key_usage, | ||
227 | unsigned int *critical); | ||
228 | int gnutls_x509_crt_set_key_usage(gnutls_x509_crt_t crt, | ||
229 | unsigned int usage); | ||
230 | |||
231 | int gnutls_x509_crt_get_proxy(gnutls_x509_crt_t cert, | ||
232 | unsigned int *critical, | ||
233 | int *pathlen, | ||
234 | char **policyLanguage, | ||
235 | char **policy, | ||
236 | size_t *sizeof_policy); | ||
237 | |||
238 | int gnutls_x509_dn_oid_known(const char *oid); | ||
239 | |||
240 | /* Read extensions by OID. */ | ||
241 | int gnutls_x509_crt_get_extension_oid(gnutls_x509_crt_t cert, | ||
242 | int indx, | ||
243 | void *oid, | ||
244 | size_t * sizeof_oid); | ||
245 | int gnutls_x509_crt_get_extension_by_oid(gnutls_x509_crt_t cert, | ||
246 | const char *oid, | ||
247 | int indx, | ||
248 | void *buf, | ||
249 | size_t * sizeof_buf, | ||
250 | unsigned int *critical); | ||
251 | |||
252 | /* Read extensions by sequence number. */ | ||
253 | int gnutls_x509_crt_get_extension_info(gnutls_x509_crt_t cert, | ||
254 | int indx, | ||
255 | void *oid, | ||
256 | size_t * sizeof_oid, | ||
257 | int *critical); | ||
258 | int gnutls_x509_crt_get_extension_data(gnutls_x509_crt_t cert, | ||
259 | int indx, | ||
260 | void *data, | ||
261 | size_t * sizeof_data); | ||
262 | |||
263 | int gnutls_x509_crt_set_extension_by_oid(gnutls_x509_crt_t crt, | ||
264 | const char *oid, | ||
265 | const void *buf, | ||
266 | size_t sizeof_buf, | ||
267 | unsigned int critical); | ||
268 | |||
269 | /* X.509 Certificate writing. | ||
270 | */ | ||
271 | int gnutls_x509_crt_set_dn_by_oid(gnutls_x509_crt_t crt, | ||
272 | const char *oid, | ||
273 | unsigned int raw_flag, | ||
274 | const void *name, | ||
275 | unsigned int sizeof_name); | ||
276 | int gnutls_x509_crt_set_issuer_dn_by_oid(gnutls_x509_crt_t crt, | ||
277 | const char *oid, | ||
278 | unsigned int raw_flag, | ||
279 | const void *name, | ||
280 | unsigned int sizeof_name); | ||
281 | int gnutls_x509_crt_set_version(gnutls_x509_crt_t crt, | ||
282 | unsigned int version); | ||
283 | int gnutls_x509_crt_set_key(gnutls_x509_crt_t crt, | ||
284 | gnutls_x509_privkey_t key); | ||
285 | int gnutls_x509_crt_set_ca_status(gnutls_x509_crt_t crt, | ||
286 | unsigned int ca); | ||
287 | int gnutls_x509_crt_set_basic_constraints(gnutls_x509_crt_t crt, | ||
288 | unsigned int ca, | ||
289 | int pathLenConstraint); | ||
290 | int gnutls_x509_crt_set_subject_alternative_name(gnutls_x509_crt_t crt, | ||
291 | gnutls_x509_subject_alt_name_t | ||
292 | type, | ||
293 | const char *data_string); | ||
294 | int gnutls_x509_crt_sign(gnutls_x509_crt_t crt, | ||
295 | gnutls_x509_crt_t issuer, | ||
296 | gnutls_x509_privkey_t issuer_key); | ||
297 | int gnutls_x509_crt_sign2(gnutls_x509_crt_t crt, | ||
298 | gnutls_x509_crt_t issuer, | ||
299 | gnutls_x509_privkey_t issuer_key, | ||
300 | gnutls_digest_algorithm_t, | ||
301 | unsigned int flags); | ||
302 | int gnutls_x509_crt_set_activation_time(gnutls_x509_crt_t cert, | ||
303 | time_t act_time); | ||
304 | int gnutls_x509_crt_set_expiration_time(gnutls_x509_crt_t cert, | ||
305 | time_t exp_time); | ||
306 | int gnutls_x509_crt_set_serial(gnutls_x509_crt_t cert, | ||
307 | const void *serial, | ||
308 | size_t serial_size); | ||
309 | |||
310 | int gnutls_x509_crt_set_subject_key_id(gnutls_x509_crt_t cert, | ||
311 | const void *id, | ||
312 | size_t id_size); | ||
313 | |||
314 | int gnutls_x509_crt_set_proxy_dn(gnutls_x509_crt_t crt, | ||
315 | gnutls_x509_crt_t eecrt, | ||
316 | unsigned int raw_flag, | ||
317 | const void *name, | ||
318 | unsigned int sizeof_name); | ||
319 | int gnutls_x509_crt_set_proxy(gnutls_x509_crt_t crt, | ||
320 | int pathLenConstraint, | ||
321 | const char *policyLanguage, | ||
322 | const char *policy, | ||
323 | size_t sizeof_policy); | ||
324 | |||
325 | typedef enum gnutls_certificate_print_formats | ||
326 | { | ||
327 | GNUTLS_X509_CRT_FULL, | ||
328 | GNUTLS_X509_CRT_ONELINE, | ||
329 | GNUTLS_X509_CRT_UNSIGNED_FULL | ||
330 | } gnutls_certificate_print_formats_t; | ||
331 | |||
332 | int gnutls_x509_crt_print(gnutls_x509_crt_t cert, | ||
333 | gnutls_certificate_print_formats_t format, | ||
334 | gnutls_datum_t *out); | ||
335 | int gnutls_x509_crl_print(gnutls_x509_crl_t crl, | ||
336 | gnutls_certificate_print_formats_t format, | ||
337 | gnutls_datum_t *out); | ||
338 | |||
339 | /* Access to internal Certificate fields. | ||
340 | */ | ||
341 | int gnutls_x509_crt_get_raw_issuer_dn(gnutls_x509_crt_t cert, | ||
342 | gnutls_datum_t * start); | ||
343 | int gnutls_x509_crt_get_raw_dn(gnutls_x509_crt_t cert, | ||
344 | gnutls_datum_t * start); | ||
345 | |||
346 | /* RDN handling. | ||
347 | */ | ||
348 | int gnutls_x509_rdn_get(const gnutls_datum_t * idn, | ||
349 | char *buf, | ||
350 | size_t * sizeof_buf); | ||
351 | int gnutls_x509_rdn_get_oid(const gnutls_datum_t * idn, | ||
352 | int indx, | ||
353 | void *buf, | ||
354 | size_t * sizeof_buf); | ||
355 | |||
356 | int gnutls_x509_rdn_get_by_oid(const gnutls_datum_t * idn, | ||
357 | const char *oid, | ||
358 | int indx, | ||
359 | unsigned int raw_flag, | ||
360 | void *buf, | ||
361 | size_t * sizeof_buf); | ||
362 | |||
363 | typedef void *gnutls_x509_dn_t; | ||
364 | |||
365 | typedef struct gnutls_x509_ava_st | ||
366 | { | ||
367 | gnutls_datum_t oid; | ||
368 | gnutls_datum_t value; | ||
369 | unsigned long value_tag; | ||
370 | } gnutls_x509_ava_st; | ||
371 | |||
372 | int gnutls_x509_crt_get_subject(gnutls_x509_crt_t cert, | ||
373 | gnutls_x509_dn_t *dn); | ||
374 | int gnutls_x509_crt_get_issuer(gnutls_x509_crt_t cert, | ||
375 | gnutls_x509_dn_t *dn); | ||
376 | int gnutls_x509_dn_get_rdn_ava(gnutls_x509_dn_t dn, | ||
377 | int irdn, | ||
378 | int iava, | ||
379 | gnutls_x509_ava_st *avast); | ||
380 | |||
381 | /* CRL handling functions. | ||
382 | */ | ||
383 | int gnutls_x509_crl_init(gnutls_x509_crl_t * crl); | ||
384 | void gnutls_x509_crl_deinit(gnutls_x509_crl_t crl); | ||
385 | |||
386 | int gnutls_x509_crl_import(gnutls_x509_crl_t crl, | ||
387 | const gnutls_datum_t * data, | ||
388 | gnutls_x509_crt_fmt_t format); | ||
389 | int gnutls_x509_crl_export(gnutls_x509_crl_t crl, | ||
390 | gnutls_x509_crt_fmt_t format, | ||
391 | void *output_data, | ||
392 | size_t * output_data_size); | ||
393 | |||
394 | int gnutls_x509_crl_get_issuer_dn(const gnutls_x509_crl_t crl, | ||
395 | char *buf, | ||
396 | size_t * sizeof_buf); | ||
397 | int gnutls_x509_crl_get_issuer_dn_by_oid(gnutls_x509_crl_t crl, | ||
398 | const char *oid, | ||
399 | int indx, | ||
400 | unsigned int raw_flag, | ||
401 | void *buf, | ||
402 | size_t * sizeof_buf); | ||
403 | int gnutls_x509_crl_get_dn_oid(gnutls_x509_crl_t crl, | ||
404 | int indx, | ||
405 | void *oid, | ||
406 | size_t * sizeof_oid); | ||
407 | |||
408 | int gnutls_x509_crl_get_signature_algorithm(gnutls_x509_crl_t crl); | ||
409 | int gnutls_x509_crl_get_signature(gnutls_x509_crl_t crl, | ||
410 | char *sig, | ||
411 | size_t *sizeof_sig); | ||
412 | int gnutls_x509_crl_get_version(gnutls_x509_crl_t crl); | ||
413 | |||
414 | time_t gnutls_x509_crl_get_this_update(gnutls_x509_crl_t crl); | ||
415 | time_t gnutls_x509_crl_get_next_update(gnutls_x509_crl_t crl); | ||
416 | |||
417 | int gnutls_x509_crl_get_crt_count(gnutls_x509_crl_t crl); | ||
418 | int gnutls_x509_crl_get_crt_serial(gnutls_x509_crl_t crl, | ||
419 | int indx, | ||
420 | unsigned char *serial, | ||
421 | size_t * serial_size, | ||
422 | time_t * t); | ||
423 | #define gnutls_x509_crl_get_certificate_count gnutls_x509_crl_get_crt_count | ||
424 | #define gnutls_x509_crl_get_certificate gnutls_x509_crl_get_crt_serial | ||
425 | |||
426 | int gnutls_x509_crl_check_issuer(gnutls_x509_crl_t crl, | ||
427 | gnutls_x509_crt_t issuer); | ||
428 | |||
429 | /* CRL writing. | ||
430 | */ | ||
431 | int gnutls_x509_crl_set_version(gnutls_x509_crl_t crl, | ||
432 | unsigned int version); | ||
433 | int gnutls_x509_crl_sign(gnutls_x509_crl_t crl, | ||
434 | gnutls_x509_crt_t issuer, | ||
435 | gnutls_x509_privkey_t issuer_key); | ||
436 | int gnutls_x509_crl_sign2(gnutls_x509_crl_t crl, | ||
437 | gnutls_x509_crt_t issuer, | ||
438 | gnutls_x509_privkey_t issuer_key, | ||
439 | gnutls_digest_algorithm_t, | ||
440 | unsigned int flags); | ||
441 | int gnutls_x509_crl_set_this_update(gnutls_x509_crl_t crl, | ||
442 | time_t act_time); | ||
443 | int gnutls_x509_crl_set_next_update(gnutls_x509_crl_t crl, | ||
444 | time_t exp_time); | ||
445 | int gnutls_x509_crl_set_crt_serial(gnutls_x509_crl_t crl, | ||
446 | const void *serial, | ||
447 | size_t serial_size, | ||
448 | time_t revocation_time); | ||
449 | int gnutls_x509_crl_set_crt(gnutls_x509_crl_t crl, | ||
450 | gnutls_x509_crt_t crt, | ||
451 | time_t revocation_time); | ||
452 | |||
453 | /* PKCS7 structures handling | ||
454 | */ | ||
455 | struct gnutls_pkcs7_int; | ||
456 | typedef struct gnutls_pkcs7_int *gnutls_pkcs7_t; | ||
457 | |||
458 | int gnutls_pkcs7_init(gnutls_pkcs7_t * pkcs7); | ||
459 | void gnutls_pkcs7_deinit(gnutls_pkcs7_t pkcs7); | ||
460 | int gnutls_pkcs7_import(gnutls_pkcs7_t pkcs7, | ||
461 | const gnutls_datum_t * data, | ||
462 | gnutls_x509_crt_fmt_t format); | ||
463 | int gnutls_pkcs7_export(gnutls_pkcs7_t pkcs7, | ||
464 | gnutls_x509_crt_fmt_t format, | ||
465 | void *output_data, | ||
466 | size_t * output_data_size); | ||
467 | |||
468 | int gnutls_pkcs7_get_crt_count(gnutls_pkcs7_t pkcs7); | ||
469 | int gnutls_pkcs7_get_crt_raw(gnutls_pkcs7_t pkcs7, | ||
470 | int indx, | ||
471 | void *certificate, | ||
472 | size_t * certificate_size); | ||
473 | |||
474 | int gnutls_pkcs7_set_crt_raw(gnutls_pkcs7_t pkcs7, | ||
475 | const gnutls_datum_t * crt); | ||
476 | int gnutls_pkcs7_set_crt(gnutls_pkcs7_t pkcs7, | ||
477 | gnutls_x509_crt_t crt); | ||
478 | int gnutls_pkcs7_delete_crt(gnutls_pkcs7_t pkcs7, | ||
479 | int indx); | ||
480 | |||
481 | int gnutls_pkcs7_get_crl_raw(gnutls_pkcs7_t pkcs7, | ||
482 | int indx, | ||
483 | void *crl, | ||
484 | size_t * crl_size); | ||
485 | int gnutls_pkcs7_get_crl_count(gnutls_pkcs7_t pkcs7); | ||
486 | |||
487 | int gnutls_pkcs7_set_crl_raw(gnutls_pkcs7_t pkcs7, | ||
488 | const gnutls_datum_t * crt); | ||
489 | int gnutls_pkcs7_set_crl(gnutls_pkcs7_t pkcs7, | ||
490 | gnutls_x509_crl_t crl); | ||
491 | int gnutls_pkcs7_delete_crl(gnutls_pkcs7_t pkcs7, | ||
492 | int indx); | ||
493 | |||
494 | /* X.509 Certificate verification functions. | ||
495 | */ | ||
496 | typedef enum gnutls_certificate_verify_flags | ||
497 | { | ||
498 | /* If set a signer does not have to be a certificate authority. This | ||
499 | * flag should normaly be disabled, unless you know what this means. | ||
500 | */ | ||
501 | GNUTLS_VERIFY_DISABLE_CA_SIGN = 1, | ||
502 | |||
503 | /* Allow only trusted CA certificates that have version 1. This is | ||
504 | * safer than GNUTLS_VERIFY_ALLOW_ANY_X509_V1_CA_CRT, and should be | ||
505 | * used instead. That way only signers in your trusted list will be | ||
506 | * allowed to have certificates of version 1. | ||
507 | */ | ||
508 | GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT = 2, | ||
509 | |||
510 | /* If a certificate is not signed by anyone trusted but exists in | ||
511 | * the trusted CA list do not treat it as trusted. | ||
512 | */ | ||
513 | GNUTLS_VERIFY_DO_NOT_ALLOW_SAME = 4, | ||
514 | |||
515 | /* Allow CA certificates that have version 1 (both root and | ||
516 | * intermediate). This might be dangerous since those haven't the | ||
517 | * basicConstraints extension. Must be used in combination with | ||
518 | * GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT. | ||
519 | */ | ||
520 | GNUTLS_VERIFY_ALLOW_ANY_X509_V1_CA_CRT = 8, | ||
521 | |||
522 | /* Allow certificates to be signed using the broken MD2 algorithm. | ||
523 | */ | ||
524 | GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2 = 16, | ||
525 | |||
526 | /* Allow certificates to be signed using the broken MD5 algorithm. | ||
527 | */ | ||
528 | GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5 = 32 | ||
529 | } gnutls_certificate_verify_flags; | ||
530 | |||
531 | int gnutls_x509_crt_check_issuer(gnutls_x509_crt_t cert, | ||
532 | gnutls_x509_crt_t issuer); | ||
533 | |||
534 | int gnutls_x509_crt_list_verify(const gnutls_x509_crt_t * cert_list, | ||
535 | int cert_list_length, | ||
536 | const gnutls_x509_crt_t * CA_list, | ||
537 | int CA_list_length, | ||
538 | const gnutls_x509_crl_t * CRL_list, | ||
539 | int CRL_list_length, | ||
540 | unsigned int flags, | ||
541 | unsigned int *verify); | ||
542 | |||
543 | int gnutls_x509_crt_verify(gnutls_x509_crt_t cert, | ||
544 | const gnutls_x509_crt_t * CA_list, | ||
545 | int CA_list_length, | ||
546 | unsigned int flags, | ||
547 | unsigned int *verify); | ||
548 | int gnutls_x509_crl_verify(gnutls_x509_crl_t crl, | ||
549 | const gnutls_x509_crt_t * CA_list, | ||
550 | int CA_list_length, | ||
551 | unsigned int flags, | ||
552 | unsigned int *verify); | ||
553 | |||
554 | int gnutls_x509_crt_check_revocation(gnutls_x509_crt_t cert, | ||
555 | const gnutls_x509_crl_t * | ||
556 | crl_list, | ||
557 | int crl_list_length); | ||
558 | |||
559 | int gnutls_x509_crt_get_fingerprint(gnutls_x509_crt_t cert, | ||
560 | gnutls_digest_algorithm_t algo, | ||
561 | void *buf, | ||
562 | size_t * sizeof_buf); | ||
563 | |||
564 | int gnutls_x509_crt_get_key_purpose_oid(gnutls_x509_crt_t cert, | ||
565 | int indx, | ||
566 | void *oid, | ||
567 | size_t * sizeof_oid, | ||
568 | unsigned int *critical); | ||
569 | int gnutls_x509_crt_set_key_purpose_oid(gnutls_x509_crt_t cert, | ||
570 | const void *oid, | ||
571 | unsigned int critical); | ||
572 | |||
573 | /* Private key handling. | ||
574 | */ | ||
575 | |||
576 | /* Flags for the gnutls_x509_privkey_export_pkcs8() function. | ||
577 | */ | ||
578 | typedef enum gnutls_pkcs_encrypt_flags_t | ||
579 | { | ||
580 | GNUTLS_PKCS_PLAIN = 1, /* if set the private key will not | ||
581 | * be encrypted. | ||
582 | */ | ||
583 | GNUTLS_PKCS_USE_PKCS12_3DES = 2, | ||
584 | GNUTLS_PKCS_USE_PKCS12_ARCFOUR = 4, | ||
585 | GNUTLS_PKCS_USE_PKCS12_RC2_40 = 8, | ||
586 | GNUTLS_PKCS_USE_PBES2_3DES = 16 | ||
587 | } gnutls_pkcs_encrypt_flags_t; | ||
588 | |||
589 | #define GNUTLS_PKCS8_PLAIN GNUTLS_PKCS_PLAIN | ||
590 | #define GNUTLS_PKCS8_USE_PKCS12_3DES GNUTLS_PKCS_USE_PKCS12_3DES | ||
591 | #define GNUTLS_PKCS8_USE_PKCS12_ARCFOUR GNUTLS_PKCS_USE_PKCS12_ARCFOUR | ||
592 | #define GNUTLS_PKCS8_USE_PKCS12_RC2_40 GNUTLS_PKCS_USE_PKCS12_RC2_40 | ||
593 | |||
594 | int gnutls_x509_privkey_init(gnutls_x509_privkey_t * key); | ||
595 | void gnutls_x509_privkey_deinit(gnutls_x509_privkey_t key); | ||
596 | int gnutls_x509_privkey_cpy(gnutls_x509_privkey_t dst, | ||
597 | gnutls_x509_privkey_t src); | ||
598 | int gnutls_x509_privkey_import(gnutls_x509_privkey_t key, | ||
599 | const gnutls_datum_t * data, | ||
600 | gnutls_x509_crt_fmt_t format); | ||
601 | int gnutls_x509_privkey_import_pkcs8(gnutls_x509_privkey_t key, | ||
602 | const gnutls_datum_t * data, | ||
603 | gnutls_x509_crt_fmt_t format, | ||
604 | const char *pass, | ||
605 | unsigned int flags); | ||
606 | int gnutls_x509_privkey_import_rsa_raw(gnutls_x509_privkey_t key, | ||
607 | const gnutls_datum_t * m, | ||
608 | const gnutls_datum_t * e, | ||
609 | const gnutls_datum_t * d, | ||
610 | const gnutls_datum_t * p, | ||
611 | const gnutls_datum_t * q, | ||
612 | const gnutls_datum_t * u); | ||
613 | int gnutls_x509_privkey_fix(gnutls_x509_privkey_t key); | ||
614 | |||
615 | int gnutls_x509_privkey_export_dsa_raw(gnutls_x509_privkey_t key, | ||
616 | gnutls_datum_t * p, | ||
617 | gnutls_datum_t * q, | ||
618 | gnutls_datum_t * g, | ||
619 | gnutls_datum_t * y, | ||
620 | gnutls_datum_t * x); | ||
621 | int gnutls_x509_privkey_import_dsa_raw(gnutls_x509_privkey_t key, | ||
622 | const gnutls_datum_t * p, | ||
623 | const gnutls_datum_t * q, | ||
624 | const gnutls_datum_t * g, | ||
625 | const gnutls_datum_t * y, | ||
626 | const gnutls_datum_t * x); | ||
627 | |||
628 | int gnutls_x509_privkey_get_pk_algorithm(gnutls_x509_privkey_t key); | ||
629 | int gnutls_x509_privkey_get_key_id(gnutls_x509_privkey_t key, | ||
630 | unsigned int flags, | ||
631 | unsigned char *output_data, | ||
632 | size_t * output_data_size); | ||
633 | |||
634 | int gnutls_x509_privkey_generate(gnutls_x509_privkey_t key, | ||
635 | gnutls_pk_algorithm_t algo, | ||
636 | unsigned int bits, | ||
637 | unsigned int flags); | ||
638 | |||
639 | int gnutls_x509_privkey_export(gnutls_x509_privkey_t key, | ||
640 | gnutls_x509_crt_fmt_t format, | ||
641 | void *output_data, | ||
642 | size_t * output_data_size); | ||
643 | int gnutls_x509_privkey_export_pkcs8(gnutls_x509_privkey_t key, | ||
644 | gnutls_x509_crt_fmt_t format, | ||
645 | const char *password, | ||
646 | unsigned int flags, | ||
647 | void *output_data, | ||
648 | size_t * output_data_size); | ||
649 | int gnutls_x509_privkey_export_rsa_raw(gnutls_x509_privkey_t key, | ||
650 | gnutls_datum_t * m, | ||
651 | gnutls_datum_t * e, | ||
652 | gnutls_datum_t * d, | ||
653 | gnutls_datum_t * p, | ||
654 | gnutls_datum_t * q, | ||
655 | gnutls_datum_t * u); | ||
656 | |||
657 | /* Signing stuff. | ||
658 | */ | ||
659 | int gnutls_x509_privkey_sign_data(gnutls_x509_privkey_t key, | ||
660 | gnutls_digest_algorithm_t digest, | ||
661 | unsigned int flags, | ||
662 | const gnutls_datum_t * data, | ||
663 | void *signature, | ||
664 | size_t * signature_size); | ||
665 | int gnutls_x509_privkey_verify_data(gnutls_x509_privkey_t key, | ||
666 | unsigned int flags, | ||
667 | const gnutls_datum_t * data, | ||
668 | const gnutls_datum_t * signature); | ||
669 | int gnutls_x509_crt_verify_data(gnutls_x509_crt_t crt, | ||
670 | unsigned int flags, | ||
671 | const gnutls_datum_t * data, | ||
672 | const gnutls_datum_t * signature); | ||
673 | |||
674 | int gnutls_x509_privkey_sign_hash(gnutls_x509_privkey_t key, | ||
675 | const gnutls_datum_t * hash, | ||
676 | gnutls_datum_t * signature); | ||
677 | |||
678 | /* Certificate request stuff. | ||
679 | */ | ||
680 | struct gnutls_x509_crq_int; | ||
681 | typedef struct gnutls_x509_crq_int *gnutls_x509_crq_t; | ||
682 | |||
683 | int gnutls_x509_crq_init(gnutls_x509_crq_t * crq); | ||
684 | void gnutls_x509_crq_deinit(gnutls_x509_crq_t crq); | ||
685 | int gnutls_x509_crq_import(gnutls_x509_crq_t crq, | ||
686 | const gnutls_datum_t * data, | ||
687 | gnutls_x509_crt_fmt_t format); | ||
688 | int gnutls_x509_crq_get_pk_algorithm(gnutls_x509_crq_t crq, | ||
689 | unsigned int *bits); | ||
690 | int gnutls_x509_crq_get_dn(gnutls_x509_crq_t crq, | ||
691 | char *buf, | ||
692 | size_t * sizeof_buf); | ||
693 | int gnutls_x509_crq_get_dn_oid(gnutls_x509_crq_t crq, | ||
694 | int indx, | ||
695 | void *oid, | ||
696 | size_t * sizeof_oid); | ||
697 | int gnutls_x509_crq_get_dn_by_oid(gnutls_x509_crq_t crq, | ||
698 | const char *oid, | ||
699 | int indx, | ||
700 | unsigned int raw_flag, | ||
701 | void *buf, | ||
702 | size_t * sizeof_buf); | ||
703 | int gnutls_x509_crq_set_dn_by_oid(gnutls_x509_crq_t crq, | ||
704 | const char *oid, | ||
705 | unsigned int raw_flag, | ||
706 | const void *name, | ||
707 | unsigned int sizeof_name); | ||
708 | int gnutls_x509_crq_set_version(gnutls_x509_crq_t crq, | ||
709 | unsigned int version); | ||
710 | int gnutls_x509_crq_set_key(gnutls_x509_crq_t crq, | ||
711 | gnutls_x509_privkey_t key); | ||
712 | int gnutls_x509_crq_sign2(gnutls_x509_crq_t crq, | ||
713 | gnutls_x509_privkey_t key, | ||
714 | gnutls_digest_algorithm_t, | ||
715 | unsigned int flags); | ||
716 | int gnutls_x509_crq_sign(gnutls_x509_crq_t crq, | ||
717 | gnutls_x509_privkey_t key); | ||
718 | |||
719 | int gnutls_x509_crq_set_challenge_password(gnutls_x509_crq_t crq, | ||
720 | const char *pass); | ||
721 | int gnutls_x509_crq_get_challenge_password(gnutls_x509_crq_t crq, | ||
722 | char *pass, | ||
723 | size_t * sizeof_pass); | ||
724 | |||
725 | int gnutls_x509_crq_set_attribute_by_oid(gnutls_x509_crq_t crq, | ||
726 | const char *oid, | ||
727 | void *buf, | ||
728 | size_t sizeof_buf); | ||
729 | int gnutls_x509_crq_get_attribute_by_oid(gnutls_x509_crq_t crq, | ||
730 | const char *oid, | ||
731 | int indx, | ||
732 | void *buf, | ||
733 | size_t * sizeof_buf); | ||
734 | |||
735 | int gnutls_x509_crq_export(gnutls_x509_crq_t crq, | ||
736 | gnutls_x509_crt_fmt_t format, | ||
737 | void *output_data, | ||
738 | size_t * output_data_size); | ||
739 | |||
740 | int gnutls_x509_crt_set_crq(gnutls_x509_crt_t crt, | ||
741 | gnutls_x509_crq_t crq); | ||
742 | |||
743 | #ifdef __cplusplus | ||
744 | } | ||
745 | #endif | ||
746 | |||
747 | #define HASH_OID_SHA1 "1.3.14.3.2.26" | ||
748 | #define HASH_OID_MD5 "1.2.840.113549.2.5" | ||
749 | #define HASH_OID_MD2 "1.2.840.113549.2.2" | ||
750 | #define HASH_OID_RMD160 "1.3.36.3.2.1" | ||
751 | #define HASH_OID_SHA256 "2.16.840.1.101.3.4.2.1" | ||
752 | #define HASH_OID_SHA384 "2.16.840.1.101.3.4.2.2" | ||
753 | #define HASH_OID_SHA512 "2.16.840.1.101.3.4.2.3" | ||
754 | |||
755 | typedef struct gnutls_x509_crl_int | ||
756 | { | ||
757 | ASN1_TYPE crl; | ||
758 | } gnutls_x509_crl_int; | ||
759 | |||
760 | typedef struct gnutls_x509_crt_int | ||
761 | { | ||
762 | ASN1_TYPE cert; | ||
763 | int use_extensions; | ||
764 | } gnutls_x509_crt_int; | ||
765 | |||
766 | #define MAX_PRIV_PARAMS_SIZE 6 /* ok for RSA and DSA */ | ||
767 | |||
768 | /* parameters should not be larger than this limit */ | ||
769 | #define DSA_PRIVATE_PARAMS 5 | ||
770 | #define DSA_PUBLIC_PARAMS 4 | ||
771 | #define RSA_PRIVATE_PARAMS 6 | ||
772 | #define RSA_PUBLIC_PARAMS 2 | ||
773 | |||
774 | #if MAX_PRIV_PARAMS_SIZE - RSA_PRIVATE_PARAMS < 0 | ||
775 | # error INCREASE MAX_PRIV_PARAMS | ||
776 | #endif | ||
777 | |||
778 | #if MAX_PRIV_PARAMS_SIZE - DSA_PRIVATE_PARAMS < 0 | ||
779 | # error INCREASE MAX_PRIV_PARAMS | ||
780 | #endif | ||
781 | |||
782 | typedef struct gnutls_x509_privkey_int | ||
783 | { | ||
784 | mpi_t params[MAX_PRIV_PARAMS_SIZE]; /* the size of params depends on the public | ||
785 | * key algorithm | ||
786 | */ | ||
787 | /* | ||
788 | * RSA: [0] is modulus | ||
789 | * [1] is public exponent | ||
790 | * [2] is private exponent | ||
791 | * [3] is prime1 (p) | ||
792 | * [4] is prime2 (q) | ||
793 | * [5] is coefficient (u == inverse of p mod q) | ||
794 | * note that other packages used inverse of q mod p, | ||
795 | * so we need to perform conversions. | ||
796 | * DSA: [0] is p | ||
797 | * [1] is q | ||
798 | * [2] is g | ||
799 | * [3] is y (public key) | ||
800 | * [4] is x (private key) | ||
801 | */ | ||
802 | int params_size; /* holds the number of params */ | ||
803 | |||
804 | gnutls_pk_algorithm_t pk_algorithm; | ||
805 | |||
806 | int crippled; /* The crippled keys will not use the ASN1_TYPE key. | ||
807 | * The encoding will only be performed at the export | ||
808 | * phase, to optimize copying etc. Cannot be used with | ||
809 | * the exported API (used internally only). | ||
810 | */ | ||
811 | ASN1_TYPE key; | ||
812 | } gnutls_x509_privkey_int; | ||
813 | |||
814 | int gnutls_x509_crt_get_issuer_dn_by_oid(gnutls_x509_crt_t cert, | ||
815 | const char *oid, | ||
816 | int indx, | ||
817 | unsigned int raw_flag, | ||
818 | void *buf, | ||
819 | size_t * sizeof_buf); | ||
820 | int gnutls_x509_crt_get_subject_alt_name(gnutls_x509_crt_t cert, | ||
821 | unsigned int seq, | ||
822 | void *ret, | ||
823 | size_t * ret_size, | ||
824 | unsigned int *critical); | ||
825 | int gnutls_x509_crt_get_dn_by_oid(gnutls_x509_crt_t cert, | ||
826 | const char *oid, | ||
827 | int indx, | ||
828 | unsigned int raw_flag, | ||
829 | void *buf, | ||
830 | size_t * sizeof_buf); | ||
831 | int gnutls_x509_crt_get_ca_status(gnutls_x509_crt_t cert, | ||
832 | unsigned int *critical); | ||
833 | int gnutls_x509_crt_get_pk_algorithm(gnutls_x509_crt_t cert, | ||
834 | unsigned int *bits); | ||
835 | |||
836 | int _gnutls_x509_crt_cpy(gnutls_x509_crt_t dest, | ||
837 | gnutls_x509_crt_t src); | ||
838 | |||
839 | int gnutls_x509_crt_get_serial(gnutls_x509_crt_t cert, | ||
840 | void *result, | ||
841 | size_t * result_size); | ||
842 | |||
843 | int _gnutls_x509_compare_raw_dn(const gnutls_datum_t * dn1, | ||
844 | const gnutls_datum_t * dn2); | ||
845 | |||
846 | int gnutls_x509_crt_check_revocation(gnutls_x509_crt_t cert, | ||
847 | const gnutls_x509_crl_t * crl_list, | ||
848 | int crl_list_length); | ||
849 | |||
850 | int _gnutls_x509_crl_cpy(gnutls_x509_crl_t dest, | ||
851 | gnutls_x509_crl_t src); | ||
852 | int _gnutls_x509_crl_get_raw_issuer_dn(gnutls_x509_crl_t crl, | ||
853 | gnutls_datum_t * dn); | ||
854 | int gnutls_x509_crl_get_crt_count(gnutls_x509_crl_t crl); | ||
855 | int gnutls_x509_crl_get_crt_serial(gnutls_x509_crl_t crl, | ||
856 | int indx, | ||
857 | unsigned char *serial, | ||
858 | size_t * serial_size, | ||
859 | time_t * t); | ||
860 | |||
861 | void gnutls_x509_crl_deinit(gnutls_x509_crl_t crl); | ||
862 | int gnutls_x509_crl_init(gnutls_x509_crl_t * crl); | ||
863 | int gnutls_x509_crl_import(gnutls_x509_crl_t crl, | ||
864 | const gnutls_datum_t * data, | ||
865 | gnutls_x509_crt_fmt_t format); | ||
866 | int gnutls_x509_crl_export(gnutls_x509_crl_t crl, | ||
867 | gnutls_x509_crt_fmt_t format, | ||
868 | void *output_data, | ||
869 | size_t * output_data_size); | ||
870 | |||
871 | int gnutls_x509_crt_init(gnutls_x509_crt_t * cert); | ||
872 | void gnutls_x509_crt_deinit(gnutls_x509_crt_t cert); | ||
873 | int gnutls_x509_crt_import(gnutls_x509_crt_t cert, | ||
874 | const gnutls_datum_t * data, | ||
875 | gnutls_x509_crt_fmt_t format); | ||
876 | int gnutls_x509_crt_export(gnutls_x509_crt_t cert, | ||
877 | gnutls_x509_crt_fmt_t format, | ||
878 | void *output_data, | ||
879 | size_t * output_data_size); | ||
880 | |||
881 | int gnutls_x509_crt_get_key_usage(gnutls_x509_crt_t cert, | ||
882 | unsigned int *key_usage, | ||
883 | unsigned int *critical); | ||
884 | int gnutls_x509_crt_get_signature_algorithm(gnutls_x509_crt_t cert); | ||
885 | int gnutls_x509_crt_get_version(gnutls_x509_crt_t cert); | ||
886 | |||
887 | int gnutls_x509_privkey_init(gnutls_x509_privkey_t * key); | ||
888 | void gnutls_x509_privkey_deinit(gnutls_x509_privkey_t key); | ||
889 | |||
890 | int gnutls_x509_privkey_generate(gnutls_x509_privkey_t key, | ||
891 | gnutls_pk_algorithm_t algo, | ||
892 | unsigned int bits, | ||
893 | unsigned int flags); | ||
894 | |||
895 | int gnutls_x509_privkey_import(gnutls_x509_privkey_t key, | ||
896 | const gnutls_datum_t * data, | ||
897 | gnutls_x509_crt_fmt_t format); | ||
898 | int gnutls_x509_privkey_get_pk_algorithm(gnutls_x509_privkey_t key); | ||
899 | int gnutls_x509_privkey_import_rsa_raw(gnutls_x509_privkey_t key, | ||
900 | const gnutls_datum_t * m, | ||
901 | const gnutls_datum_t * e, | ||
902 | const gnutls_datum_t * d, | ||
903 | const gnutls_datum_t * p, | ||
904 | const gnutls_datum_t * q, | ||
905 | const gnutls_datum_t * u); | ||
906 | int gnutls_x509_privkey_export_rsa_raw(gnutls_x509_privkey_t key, | ||
907 | gnutls_datum_t * m, | ||
908 | gnutls_datum_t * e, | ||
909 | gnutls_datum_t * d, | ||
910 | gnutls_datum_t * p, | ||
911 | gnutls_datum_t * q, | ||
912 | gnutls_datum_t * u); | ||
913 | int gnutls_x509_privkey_export(gnutls_x509_privkey_t key, | ||
914 | gnutls_x509_crt_fmt_t format, | ||
915 | void *output_data, | ||
916 | size_t * output_data_size); | ||
917 | |||
918 | #define GNUTLS_CRL_REASON_UNUSED 128 | ||
919 | #define GNUTLS_CRL_REASON_KEY_COMPROMISE 64 | ||
920 | #define GNUTLS_CRL_REASON_CA_COMPROMISE 32 | ||
921 | #define GNUTLS_CRL_REASON_AFFILIATION_CHANGED 16 | ||
922 | #define GNUTLS_CRL_REASON_SUPERSEEDED 8 | ||
923 | #define GNUTLS_CRL_REASON_CESSATION_OF_OPERATION 4 | ||
924 | #define GNUTLS_CRL_REASON_CERTIFICATE_HOLD 2 | ||
925 | #define GNUTLS_CRL_REASON_PRIVILEGE_WITHDRAWN 1 | ||
926 | #define GNUTLS_CRL_REASON_AA_COMPROMISE 32768 | ||
927 | |||
928 | #endif | ||
diff --git a/src/daemon/https/x509/x509_privkey.c b/src/daemon/https/x509/x509_privkey.c new file mode 100644 index 00000000..f5c64dee --- /dev/null +++ b/src/daemon/https/x509/x509_privkey.c | |||
@@ -0,0 +1,1509 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <gnutls_int.h> | ||
26 | #include <gnutls_datum.h> | ||
27 | #include <gnutls_global.h> | ||
28 | #include <gnutls_errors.h> | ||
29 | #include <gnutls_rsa_export.h> | ||
30 | #include <gnutls_sig.h> | ||
31 | #include <common.h> | ||
32 | #include <gnutls_x509.h> | ||
33 | #include <x509_b64.h> | ||
34 | #include <x509.h> | ||
35 | #include <dn.h> | ||
36 | #include <mpi.h> | ||
37 | #include <extensions.h> | ||
38 | #include <sign.h> | ||
39 | #include <dsa.h> | ||
40 | #include <verify.h> | ||
41 | |||
42 | static int _gnutls_asn1_encode_rsa (ASN1_TYPE * c2, mpi_t * params); | ||
43 | int _gnutls_asn1_encode_dsa (ASN1_TYPE * c2, mpi_t * params); | ||
44 | |||
45 | /* remove this when libgcrypt can handle the PKCS #1 coefficients from | ||
46 | * rsa keys | ||
47 | */ | ||
48 | #define CALC_COEFF 1 | ||
49 | |||
50 | /** | ||
51 | * gnutls_x509_privkey_init - This function initializes a gnutls_crl structure | ||
52 | * @key: The structure to be initialized | ||
53 | * | ||
54 | * This function will initialize an private key structure. | ||
55 | * | ||
56 | * Returns 0 on success. | ||
57 | * | ||
58 | **/ | ||
59 | int | ||
60 | gnutls_x509_privkey_init (gnutls_x509_privkey_t * key) | ||
61 | { | ||
62 | *key = gnutls_calloc (1, sizeof (gnutls_x509_privkey_int)); | ||
63 | |||
64 | if (*key) | ||
65 | { | ||
66 | (*key)->key = ASN1_TYPE_EMPTY; | ||
67 | (*key)->pk_algorithm = GNUTLS_PK_UNKNOWN; | ||
68 | return 0; /* success */ | ||
69 | } | ||
70 | |||
71 | return GNUTLS_E_MEMORY_ERROR; | ||
72 | } | ||
73 | |||
74 | /** | ||
75 | * gnutls_x509_privkey_deinit - This function deinitializes memory used by a gnutls_x509_privkey_t structure | ||
76 | * @key: The structure to be initialized | ||
77 | * | ||
78 | * This function will deinitialize a private key structure. | ||
79 | * | ||
80 | **/ | ||
81 | void | ||
82 | gnutls_x509_privkey_deinit (gnutls_x509_privkey_t key) | ||
83 | { | ||
84 | int i; | ||
85 | |||
86 | if (!key) | ||
87 | return; | ||
88 | |||
89 | for (i = 0; i < key->params_size; i++) | ||
90 | { | ||
91 | _gnutls_mpi_release (&key->params[i]); | ||
92 | } | ||
93 | |||
94 | asn1_delete_structure (&key->key); | ||
95 | gnutls_free (key); | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * gnutls_x509_privkey_cpy - This function copies a private key | ||
100 | * @dst: The destination key, which should be initialized. | ||
101 | * @src: The source key | ||
102 | * | ||
103 | * This function will copy a private key from source to destination key. | ||
104 | * | ||
105 | **/ | ||
106 | int | ||
107 | gnutls_x509_privkey_cpy (gnutls_x509_privkey_t dst, gnutls_x509_privkey_t src) | ||
108 | { | ||
109 | int i, ret; | ||
110 | |||
111 | if (!src || !dst) | ||
112 | return GNUTLS_E_INVALID_REQUEST; | ||
113 | |||
114 | for (i = 0; i < src->params_size; i++) | ||
115 | { | ||
116 | dst->params[i] = _gnutls_mpi_copy (src->params[i]); | ||
117 | if (dst->params[i] == NULL) | ||
118 | return GNUTLS_E_MEMORY_ERROR; | ||
119 | } | ||
120 | |||
121 | dst->params_size = src->params_size; | ||
122 | dst->pk_algorithm = src->pk_algorithm; | ||
123 | dst->crippled = src->crippled; | ||
124 | |||
125 | if (!src->crippled) | ||
126 | { | ||
127 | switch (dst->pk_algorithm) | ||
128 | { | ||
129 | case GNUTLS_PK_RSA: | ||
130 | ret = _gnutls_asn1_encode_rsa (&dst->key, dst->params); | ||
131 | if (ret < 0) | ||
132 | { | ||
133 | gnutls_assert (); | ||
134 | return ret; | ||
135 | } | ||
136 | break; | ||
137 | default: | ||
138 | gnutls_assert (); | ||
139 | return GNUTLS_E_INVALID_REQUEST; | ||
140 | } | ||
141 | } | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | /* Converts an RSA PKCS#1 key to | ||
147 | * an internal structure (gnutls_private_key) | ||
148 | */ | ||
149 | ASN1_TYPE | ||
150 | _gnutls_privkey_decode_pkcs1_rsa_key (const gnutls_datum_t * raw_key, | ||
151 | gnutls_x509_privkey_t pkey) | ||
152 | { | ||
153 | int result; | ||
154 | ASN1_TYPE pkey_asn; | ||
155 | |||
156 | if ((result = asn1_create_element (_gnutls_get_gnutls_asn (), | ||
157 | "GNUTLS.RSAPrivateKey", | ||
158 | &pkey_asn)) != ASN1_SUCCESS) | ||
159 | { | ||
160 | gnutls_assert (); | ||
161 | return NULL; | ||
162 | } | ||
163 | |||
164 | if ((sizeof (pkey->params) / sizeof (mpi_t)) < RSA_PRIVATE_PARAMS) | ||
165 | { | ||
166 | gnutls_assert (); | ||
167 | /* internal error. Increase the mpi_ts in params */ | ||
168 | return NULL; | ||
169 | } | ||
170 | |||
171 | result = asn1_der_decoding (&pkey_asn, raw_key->data, raw_key->size, NULL); | ||
172 | if (result != ASN1_SUCCESS) | ||
173 | { | ||
174 | gnutls_assert (); | ||
175 | goto error; | ||
176 | } | ||
177 | |||
178 | if ((result = _gnutls_x509_read_int (pkey_asn, "modulus", &pkey->params[0])) | ||
179 | < 0) | ||
180 | { | ||
181 | gnutls_assert (); | ||
182 | goto error; | ||
183 | } | ||
184 | |||
185 | if ((result = _gnutls_x509_read_int (pkey_asn, "publicExponent", | ||
186 | &pkey->params[1])) < 0) | ||
187 | { | ||
188 | gnutls_assert (); | ||
189 | goto error; | ||
190 | } | ||
191 | |||
192 | if ((result = _gnutls_x509_read_int (pkey_asn, "privateExponent", | ||
193 | &pkey->params[2])) < 0) | ||
194 | { | ||
195 | gnutls_assert (); | ||
196 | goto error; | ||
197 | } | ||
198 | |||
199 | if ((result = _gnutls_x509_read_int (pkey_asn, "prime1", &pkey->params[3])) | ||
200 | < 0) | ||
201 | { | ||
202 | gnutls_assert (); | ||
203 | goto error; | ||
204 | } | ||
205 | |||
206 | if ((result = _gnutls_x509_read_int (pkey_asn, "prime2", &pkey->params[4])) | ||
207 | < 0) | ||
208 | { | ||
209 | gnutls_assert (); | ||
210 | goto error; | ||
211 | } | ||
212 | |||
213 | #ifdef CALC_COEFF | ||
214 | /* Calculate the coefficient. This is because the gcrypt | ||
215 | * library is uses the p,q in the reverse order. | ||
216 | */ | ||
217 | pkey->params[5] = | ||
218 | _gnutls_mpi_snew (_gnutls_mpi_get_nbits (pkey->params[0])); | ||
219 | |||
220 | if (pkey->params[5] == NULL) | ||
221 | { | ||
222 | gnutls_assert (); | ||
223 | goto error; | ||
224 | } | ||
225 | |||
226 | _gnutls_mpi_invm (pkey->params[5], pkey->params[3], pkey->params[4]); | ||
227 | /* p, q */ | ||
228 | #else | ||
229 | if ((result = _gnutls_x509_read_int (pkey_asn, "coefficient", | ||
230 | &pkey->params[5])) < 0) | ||
231 | { | ||
232 | gnutls_assert (); | ||
233 | goto error; | ||
234 | } | ||
235 | #endif | ||
236 | pkey->params_size = 6; | ||
237 | |||
238 | return pkey_asn; | ||
239 | |||
240 | error:asn1_delete_structure (&pkey_asn); | ||
241 | _gnutls_mpi_release (&pkey->params[0]); | ||
242 | _gnutls_mpi_release (&pkey->params[1]); | ||
243 | _gnutls_mpi_release (&pkey->params[2]); | ||
244 | _gnutls_mpi_release (&pkey->params[3]); | ||
245 | _gnutls_mpi_release (&pkey->params[4]); | ||
246 | _gnutls_mpi_release (&pkey->params[5]); | ||
247 | return NULL; | ||
248 | |||
249 | } | ||
250 | |||
251 | static ASN1_TYPE | ||
252 | decode_dsa_key (const gnutls_datum_t * raw_key, gnutls_x509_privkey_t pkey) | ||
253 | { | ||
254 | int result; | ||
255 | ASN1_TYPE dsa_asn; | ||
256 | |||
257 | if ((result = asn1_create_element (_gnutls_get_gnutls_asn (), | ||
258 | "GNUTLS.DSAPrivateKey", | ||
259 | &dsa_asn)) != ASN1_SUCCESS) | ||
260 | { | ||
261 | gnutls_assert (); | ||
262 | return NULL; | ||
263 | } | ||
264 | |||
265 | if ((sizeof (pkey->params) / sizeof (mpi_t)) < DSA_PRIVATE_PARAMS) | ||
266 | { | ||
267 | gnutls_assert (); | ||
268 | /* internal error. Increase the mpi_ts in params */ | ||
269 | return NULL; | ||
270 | } | ||
271 | |||
272 | result = asn1_der_decoding (&dsa_asn, raw_key->data, raw_key->size, NULL); | ||
273 | if (result != ASN1_SUCCESS) | ||
274 | { | ||
275 | gnutls_assert (); | ||
276 | goto error; | ||
277 | } | ||
278 | |||
279 | if ((result = _gnutls_x509_read_int (dsa_asn, "p", &pkey->params[0])) < 0) | ||
280 | { | ||
281 | gnutls_assert (); | ||
282 | goto error; | ||
283 | } | ||
284 | |||
285 | if ((result = _gnutls_x509_read_int (dsa_asn, "q", &pkey->params[1])) < 0) | ||
286 | { | ||
287 | gnutls_assert (); | ||
288 | goto error; | ||
289 | } | ||
290 | |||
291 | if ((result = _gnutls_x509_read_int (dsa_asn, "g", &pkey->params[2])) < 0) | ||
292 | { | ||
293 | gnutls_assert (); | ||
294 | goto error; | ||
295 | } | ||
296 | |||
297 | if ((result = _gnutls_x509_read_int (dsa_asn, "Y", &pkey->params[3])) < 0) | ||
298 | { | ||
299 | gnutls_assert (); | ||
300 | goto error; | ||
301 | } | ||
302 | |||
303 | if ((result = | ||
304 | _gnutls_x509_read_int (dsa_asn, "priv", &pkey->params[4])) < 0) | ||
305 | { | ||
306 | gnutls_assert (); | ||
307 | goto error; | ||
308 | } | ||
309 | pkey->params_size = 5; | ||
310 | |||
311 | return dsa_asn; | ||
312 | |||
313 | error:asn1_delete_structure (&dsa_asn); | ||
314 | _gnutls_mpi_release (&pkey->params[0]); | ||
315 | _gnutls_mpi_release (&pkey->params[1]); | ||
316 | _gnutls_mpi_release (&pkey->params[2]); | ||
317 | _gnutls_mpi_release (&pkey->params[3]); | ||
318 | _gnutls_mpi_release (&pkey->params[4]); | ||
319 | return NULL; | ||
320 | |||
321 | } | ||
322 | |||
323 | #define PEM_KEY_DSA "DSA PRIVATE KEY" | ||
324 | #define PEM_KEY_RSA "RSA PRIVATE KEY" | ||
325 | |||
326 | /** | ||
327 | * gnutls_x509_privkey_import - This function will import a DER or PEM encoded key | ||
328 | * @key: The structure to store the parsed key | ||
329 | * @data: The DER or PEM encoded certificate. | ||
330 | * @format: One of DER or PEM | ||
331 | * | ||
332 | * This function will convert the given DER or PEM encoded key | ||
333 | * to the native gnutls_x509_privkey_t format. The output will be stored in @key . | ||
334 | * | ||
335 | * If the key is PEM encoded it should have a header of "RSA PRIVATE KEY", or | ||
336 | * "DSA PRIVATE KEY". | ||
337 | * | ||
338 | * Returns 0 on success. | ||
339 | * | ||
340 | **/ | ||
341 | int | ||
342 | gnutls_x509_privkey_import (gnutls_x509_privkey_t key, | ||
343 | const gnutls_datum_t * data, | ||
344 | gnutls_x509_crt_fmt_t format) | ||
345 | { | ||
346 | int result = 0, need_free = 0; | ||
347 | gnutls_datum_t _data; | ||
348 | |||
349 | if (key == NULL) | ||
350 | { | ||
351 | gnutls_assert (); | ||
352 | return GNUTLS_E_INVALID_REQUEST; | ||
353 | } | ||
354 | |||
355 | _data.data = data->data; | ||
356 | _data.size = data->size; | ||
357 | |||
358 | key->pk_algorithm = GNUTLS_PK_UNKNOWN; | ||
359 | |||
360 | /* If the Certificate is in PEM format then decode it | ||
361 | */ | ||
362 | if (format == GNUTLS_X509_FMT_PEM) | ||
363 | { | ||
364 | opaque *out; | ||
365 | |||
366 | /* Try the first header */ | ||
367 | result | ||
368 | = _gnutls_fbase64_decode (PEM_KEY_RSA, data->data, data->size, &out); | ||
369 | key->pk_algorithm = GNUTLS_PK_RSA; | ||
370 | |||
371 | // TODO rm | ||
372 | // if (result == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR) | ||
373 | // { | ||
374 | // /* try for the second header */ | ||
375 | // result = _gnutls_fbase64_decode(PEM_KEY_DSA, data->data, data->size, | ||
376 | // &out); | ||
377 | // key->pk_algorithm = GNUTLS_PK_DSA; | ||
378 | // | ||
379 | // if (result <= 0) | ||
380 | // { | ||
381 | // if (result == 0) | ||
382 | // result = GNUTLS_E_INTERNAL_ERROR; | ||
383 | // gnutls_assert (); | ||
384 | // return result; | ||
385 | // } | ||
386 | // } | ||
387 | |||
388 | _data.data = out; | ||
389 | _data.size = result; | ||
390 | |||
391 | need_free = 1; | ||
392 | } | ||
393 | |||
394 | if (key->pk_algorithm == GNUTLS_PK_RSA) | ||
395 | { | ||
396 | key->key = _gnutls_privkey_decode_pkcs1_rsa_key (&_data, key); | ||
397 | if (key->key == NULL) | ||
398 | gnutls_assert (); | ||
399 | } | ||
400 | else | ||
401 | { | ||
402 | /* Try decoding with both, and accept the one that | ||
403 | * succeeds. | ||
404 | */ | ||
405 | key->pk_algorithm = GNUTLS_PK_RSA; | ||
406 | key->key = _gnutls_privkey_decode_pkcs1_rsa_key (&_data, key); | ||
407 | |||
408 | // TODO rm | ||
409 | // if (key->key == NULL) | ||
410 | // { | ||
411 | // key->pk_algorithm = GNUTLS_PK_DSA; | ||
412 | // key->key = decode_dsa_key(&_data, key); | ||
413 | // if (key->key == NULL) | ||
414 | // gnutls_assert(); | ||
415 | // } | ||
416 | } | ||
417 | |||
418 | if (key->key == NULL) | ||
419 | { | ||
420 | gnutls_assert (); | ||
421 | result = GNUTLS_E_ASN1_DER_ERROR; | ||
422 | goto cleanup; | ||
423 | } | ||
424 | |||
425 | if (need_free) | ||
426 | _gnutls_free_datum (&_data); | ||
427 | |||
428 | /* The key has now been decoded. | ||
429 | */ | ||
430 | |||
431 | return 0; | ||
432 | |||
433 | cleanup:key->pk_algorithm = GNUTLS_PK_UNKNOWN; | ||
434 | if (need_free) | ||
435 | _gnutls_free_datum (&_data); | ||
436 | return result; | ||
437 | } | ||
438 | |||
439 | #define FREE_RSA_PRIVATE_PARAMS for (i=0;i<RSA_PRIVATE_PARAMS;i++) \ | ||
440 | _gnutls_mpi_release(&key->params[i]) | ||
441 | #define FREE_DSA_PRIVATE_PARAMS for (i=0;i<DSA_PRIVATE_PARAMS;i++) \ | ||
442 | _gnutls_mpi_release(&key->params[i]) | ||
443 | |||
444 | /** | ||
445 | * gnutls_x509_privkey_import_rsa_raw - This function will import a raw RSA key | ||
446 | * @key: The structure to store the parsed key | ||
447 | * @m: holds the modulus | ||
448 | * @e: holds the public exponent | ||
449 | * @d: holds the private exponent | ||
450 | * @p: holds the first prime (p) | ||
451 | * @q: holds the second prime (q) | ||
452 | * @u: holds the coefficient | ||
453 | * | ||
454 | * This function will convert the given RSA raw parameters | ||
455 | * to the native gnutls_x509_privkey_t format. The output will be stored in @key. | ||
456 | * | ||
457 | **/ | ||
458 | int | ||
459 | gnutls_x509_privkey_import_rsa_raw (gnutls_x509_privkey_t key, | ||
460 | const gnutls_datum_t * m, | ||
461 | const gnutls_datum_t * e, | ||
462 | const gnutls_datum_t * d, | ||
463 | const gnutls_datum_t * p, | ||
464 | const gnutls_datum_t * q, | ||
465 | const gnutls_datum_t * u) | ||
466 | { | ||
467 | int i = 0, ret; | ||
468 | size_t siz = 0; | ||
469 | |||
470 | if (key == NULL) | ||
471 | { | ||
472 | gnutls_assert (); | ||
473 | return GNUTLS_E_INVALID_REQUEST; | ||
474 | } | ||
475 | |||
476 | siz = m->size; | ||
477 | if (_gnutls_mpi_scan_nz (&key->params[0], m->data, &siz)) | ||
478 | { | ||
479 | gnutls_assert (); | ||
480 | FREE_RSA_PRIVATE_PARAMS; | ||
481 | return GNUTLS_E_MPI_SCAN_FAILED; | ||
482 | } | ||
483 | |||
484 | siz = e->size; | ||
485 | if (_gnutls_mpi_scan_nz (&key->params[1], e->data, &siz)) | ||
486 | { | ||
487 | gnutls_assert (); | ||
488 | FREE_RSA_PRIVATE_PARAMS; | ||
489 | return GNUTLS_E_MPI_SCAN_FAILED; | ||
490 | } | ||
491 | |||
492 | siz = d->size; | ||
493 | if (_gnutls_mpi_scan_nz (&key->params[2], d->data, &siz)) | ||
494 | { | ||
495 | gnutls_assert (); | ||
496 | FREE_RSA_PRIVATE_PARAMS; | ||
497 | return GNUTLS_E_MPI_SCAN_FAILED; | ||
498 | } | ||
499 | |||
500 | siz = p->size; | ||
501 | if (_gnutls_mpi_scan_nz (&key->params[3], p->data, &siz)) | ||
502 | { | ||
503 | gnutls_assert (); | ||
504 | FREE_RSA_PRIVATE_PARAMS; | ||
505 | return GNUTLS_E_MPI_SCAN_FAILED; | ||
506 | } | ||
507 | |||
508 | siz = q->size; | ||
509 | if (_gnutls_mpi_scan_nz (&key->params[4], q->data, &siz)) | ||
510 | { | ||
511 | gnutls_assert (); | ||
512 | FREE_RSA_PRIVATE_PARAMS; | ||
513 | return GNUTLS_E_MPI_SCAN_FAILED; | ||
514 | } | ||
515 | |||
516 | #ifdef CALC_COEFF | ||
517 | key->params[5] = _gnutls_mpi_snew (_gnutls_mpi_get_nbits (key->params[0])); | ||
518 | |||
519 | if (key->params[5] == NULL) | ||
520 | { | ||
521 | gnutls_assert (); | ||
522 | FREE_RSA_PRIVATE_PARAMS; | ||
523 | return GNUTLS_E_MEMORY_ERROR; | ||
524 | } | ||
525 | |||
526 | _gnutls_mpi_invm (key->params[5], key->params[3], key->params[4]); | ||
527 | #else | ||
528 | siz = u->size; | ||
529 | if (_gnutls_mpi_scan_nz (&key->params[5], u->data, &siz)) | ||
530 | { | ||
531 | gnutls_assert (); | ||
532 | FREE_RSA_PRIVATE_PARAMS; | ||
533 | return GNUTLS_E_MPI_SCAN_FAILED; | ||
534 | } | ||
535 | #endif | ||
536 | |||
537 | if (!key->crippled) | ||
538 | { | ||
539 | ret = _gnutls_asn1_encode_rsa (&key->key, key->params); | ||
540 | if (ret < 0) | ||
541 | { | ||
542 | gnutls_assert (); | ||
543 | FREE_RSA_PRIVATE_PARAMS; | ||
544 | return ret; | ||
545 | } | ||
546 | } | ||
547 | |||
548 | key->params_size = RSA_PRIVATE_PARAMS; | ||
549 | key->pk_algorithm = GNUTLS_PK_RSA; | ||
550 | |||
551 | return 0; | ||
552 | |||
553 | } | ||
554 | |||
555 | /** | ||
556 | * gnutls_x509_privkey_get_pk_algorithm - This function returns the key's PublicKey algorithm | ||
557 | * @key: should contain a gnutls_x509_privkey_t structure | ||
558 | * | ||
559 | * This function will return the public key algorithm of a private | ||
560 | * key. | ||
561 | * | ||
562 | * Returns a member of the gnutls_pk_algorithm_t enumeration on success, | ||
563 | * or a negative value on error. | ||
564 | * | ||
565 | **/ | ||
566 | int | ||
567 | gnutls_x509_privkey_get_pk_algorithm (gnutls_x509_privkey_t key) | ||
568 | { | ||
569 | if (key == NULL) | ||
570 | { | ||
571 | gnutls_assert (); | ||
572 | return GNUTLS_E_INVALID_REQUEST; | ||
573 | } | ||
574 | |||
575 | return key->pk_algorithm; | ||
576 | } | ||
577 | |||
578 | /** | ||
579 | * gnutls_x509_privkey_export - This function will export the private key | ||
580 | * @key: Holds the key | ||
581 | * @format: the format of output params. One of PEM or DER. | ||
582 | * @output_data: will contain a private key PEM or DER encoded | ||
583 | * @output_data_size: holds the size of output_data (and will be | ||
584 | * replaced by the actual size of parameters) | ||
585 | * | ||
586 | * This function will export the private key to a PKCS1 structure for | ||
587 | * RSA keys, or an integer sequence for DSA keys. The DSA keys are in | ||
588 | * the same format with the parameters used by openssl. | ||
589 | * | ||
590 | * If the buffer provided is not long enough to hold the output, then | ||
591 | * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will | ||
592 | * be returned. | ||
593 | * | ||
594 | * If the structure is PEM encoded, it will have a header | ||
595 | * of "BEGIN RSA PRIVATE KEY". | ||
596 | * | ||
597 | * Return value: In case of failure a negative value will be | ||
598 | * returned, and 0 on success. | ||
599 | * | ||
600 | **/ | ||
601 | int | ||
602 | gnutls_x509_privkey_export (gnutls_x509_privkey_t key, | ||
603 | gnutls_x509_crt_fmt_t format, | ||
604 | void *output_data, size_t * output_data_size) | ||
605 | { | ||
606 | char *msg; | ||
607 | int ret; | ||
608 | |||
609 | if (key == NULL) | ||
610 | { | ||
611 | gnutls_assert (); | ||
612 | return GNUTLS_E_INVALID_REQUEST; | ||
613 | } | ||
614 | |||
615 | if (key->pk_algorithm == GNUTLS_PK_RSA) | ||
616 | msg = PEM_KEY_RSA; | ||
617 | else | ||
618 | msg = NULL; | ||
619 | |||
620 | if (key->crippled) | ||
621 | { /* encode the parameters on the fly. | ||
622 | */ | ||
623 | switch (key->pk_algorithm) | ||
624 | { | ||
625 | case GNUTLS_PK_RSA: | ||
626 | ret = _gnutls_asn1_encode_rsa (&key->key, key->params); | ||
627 | if (ret < 0) | ||
628 | { | ||
629 | gnutls_assert (); | ||
630 | return ret; | ||
631 | } | ||
632 | break; | ||
633 | default: | ||
634 | gnutls_assert (); | ||
635 | return GNUTLS_E_INVALID_REQUEST; | ||
636 | } | ||
637 | } | ||
638 | |||
639 | return _gnutls_x509_export_int (key->key, format, msg, output_data, | ||
640 | output_data_size); | ||
641 | } | ||
642 | |||
643 | /** | ||
644 | * gnutls_x509_privkey_export_rsa_raw - This function will export the RSA private key | ||
645 | * @key: a structure that holds the rsa parameters | ||
646 | * @m: will hold the modulus | ||
647 | * @e: will hold the public exponent | ||
648 | * @d: will hold the private exponent | ||
649 | * @p: will hold the first prime (p) | ||
650 | * @q: will hold the second prime (q) | ||
651 | * @u: will hold the coefficient | ||
652 | * | ||
653 | * This function will export the RSA private key's parameters found in the given | ||
654 | * structure. The new parameters will be allocated using | ||
655 | * gnutls_malloc() and will be stored in the appropriate datum. | ||
656 | * | ||
657 | **/ | ||
658 | int | ||
659 | gnutls_x509_privkey_export_rsa_raw (gnutls_x509_privkey_t key, | ||
660 | gnutls_datum_t * m, | ||
661 | gnutls_datum_t * e, | ||
662 | gnutls_datum_t * d, | ||
663 | gnutls_datum_t * p, | ||
664 | gnutls_datum_t * q, gnutls_datum_t * u) | ||
665 | { | ||
666 | int ret; | ||
667 | mpi_t coeff = NULL; | ||
668 | |||
669 | if (key == NULL) | ||
670 | { | ||
671 | gnutls_assert (); | ||
672 | return GNUTLS_E_INVALID_REQUEST; | ||
673 | } | ||
674 | |||
675 | m->data = e->data = d->data = p->data = q->data = u->data = NULL; | ||
676 | m->size = e->size = d->size = p->size = q->size = u->size = 0; | ||
677 | |||
678 | ret = _gnutls_mpi_dprint (m, key->params[0]); | ||
679 | if (ret < 0) | ||
680 | { | ||
681 | gnutls_assert (); | ||
682 | goto error; | ||
683 | } | ||
684 | |||
685 | /* E */ | ||
686 | ret = _gnutls_mpi_dprint (e, key->params[1]); | ||
687 | if (ret < 0) | ||
688 | { | ||
689 | gnutls_assert (); | ||
690 | goto error; | ||
691 | } | ||
692 | |||
693 | /* D */ | ||
694 | ret = _gnutls_mpi_dprint (d, key->params[2]); | ||
695 | if (ret < 0) | ||
696 | { | ||
697 | gnutls_assert (); | ||
698 | goto error; | ||
699 | } | ||
700 | |||
701 | /* P */ | ||
702 | ret = _gnutls_mpi_dprint (p, key->params[3]); | ||
703 | if (ret < 0) | ||
704 | { | ||
705 | gnutls_assert (); | ||
706 | goto error; | ||
707 | } | ||
708 | |||
709 | /* Q */ | ||
710 | ret = _gnutls_mpi_dprint (q, key->params[4]); | ||
711 | if (ret < 0) | ||
712 | { | ||
713 | gnutls_assert (); | ||
714 | goto error; | ||
715 | } | ||
716 | |||
717 | #ifdef CALC_COEFF | ||
718 | coeff = _gnutls_mpi_snew (_gnutls_mpi_get_nbits (key->params[0])); | ||
719 | |||
720 | if (coeff == NULL) | ||
721 | { | ||
722 | gnutls_assert (); | ||
723 | ret = GNUTLS_E_MEMORY_ERROR; | ||
724 | goto error; | ||
725 | } | ||
726 | |||
727 | _gnutls_mpi_invm (coeff, key->params[4], key->params[3]); | ||
728 | ret = _gnutls_mpi_dprint (u, coeff); | ||
729 | if (ret < 0) | ||
730 | { | ||
731 | gnutls_assert (); | ||
732 | goto error; | ||
733 | } | ||
734 | |||
735 | _gnutls_mpi_release (&coeff); | ||
736 | #else | ||
737 | /* U */ | ||
738 | ret = _gnutls_mpi_dprint (u, key->params[5]); | ||
739 | if (ret < 0) | ||
740 | { | ||
741 | gnutls_assert (); | ||
742 | goto error; | ||
743 | } | ||
744 | #endif | ||
745 | |||
746 | return 0; | ||
747 | |||
748 | error:_gnutls_free_datum (m); | ||
749 | _gnutls_free_datum (d); | ||
750 | _gnutls_free_datum (e); | ||
751 | _gnutls_free_datum (p); | ||
752 | _gnutls_free_datum (q); | ||
753 | _gnutls_mpi_release (&coeff); | ||
754 | |||
755 | return ret; | ||
756 | } | ||
757 | |||
758 | /** | ||
759 | * gnutls_x509_privkey_export_dsa_raw - This function will export the DSA private key | ||
760 | * @params: a structure that holds the DSA parameters | ||
761 | * @p: will hold the p | ||
762 | * @q: will hold the q | ||
763 | * @g: will hold the g | ||
764 | * @y: will hold the y | ||
765 | * @x: will hold the x | ||
766 | * | ||
767 | * This function will export the DSA private key's parameters found in the given | ||
768 | * structure. The new parameters will be allocated using | ||
769 | * gnutls_malloc() and will be stored in the appropriate datum. | ||
770 | * | ||
771 | **/ | ||
772 | int | ||
773 | gnutls_x509_privkey_export_dsa_raw (gnutls_x509_privkey_t key, | ||
774 | gnutls_datum_t * p, | ||
775 | gnutls_datum_t * q, | ||
776 | gnutls_datum_t * g, | ||
777 | gnutls_datum_t * y, gnutls_datum_t * x) | ||
778 | { | ||
779 | int ret; | ||
780 | |||
781 | if (key == NULL) | ||
782 | { | ||
783 | gnutls_assert (); | ||
784 | return GNUTLS_E_INVALID_REQUEST; | ||
785 | } | ||
786 | |||
787 | /* P */ | ||
788 | ret = _gnutls_mpi_dprint (p, key->params[0]); | ||
789 | if (ret < 0) | ||
790 | { | ||
791 | gnutls_assert (); | ||
792 | return ret; | ||
793 | } | ||
794 | |||
795 | /* Q */ | ||
796 | ret = _gnutls_mpi_dprint (q, key->params[1]); | ||
797 | if (ret < 0) | ||
798 | { | ||
799 | gnutls_assert (); | ||
800 | _gnutls_free_datum (p); | ||
801 | return ret; | ||
802 | } | ||
803 | |||
804 | /* G */ | ||
805 | ret = _gnutls_mpi_dprint (g, key->params[2]); | ||
806 | if (ret < 0) | ||
807 | { | ||
808 | gnutls_assert (); | ||
809 | _gnutls_free_datum (p); | ||
810 | _gnutls_free_datum (q); | ||
811 | return ret; | ||
812 | } | ||
813 | |||
814 | /* Y */ | ||
815 | ret = _gnutls_mpi_dprint (y, key->params[3]); | ||
816 | if (ret < 0) | ||
817 | { | ||
818 | gnutls_assert (); | ||
819 | _gnutls_free_datum (p); | ||
820 | _gnutls_free_datum (g); | ||
821 | _gnutls_free_datum (q); | ||
822 | return ret; | ||
823 | } | ||
824 | |||
825 | /* X */ | ||
826 | ret = _gnutls_mpi_dprint (x, key->params[4]); | ||
827 | if (ret < 0) | ||
828 | { | ||
829 | gnutls_assert (); | ||
830 | _gnutls_free_datum (y); | ||
831 | _gnutls_free_datum (p); | ||
832 | _gnutls_free_datum (g); | ||
833 | _gnutls_free_datum (q); | ||
834 | return ret; | ||
835 | } | ||
836 | |||
837 | return 0; | ||
838 | } | ||
839 | |||
840 | /* Encodes the RSA parameters into an ASN.1 RSA private key structure. | ||
841 | */ | ||
842 | static int | ||
843 | _gnutls_asn1_encode_rsa (ASN1_TYPE * c2, mpi_t * params) | ||
844 | { | ||
845 | int result, i; | ||
846 | size_t size[8], total; | ||
847 | opaque *m_data, *pube_data, *prie_data; | ||
848 | opaque *p1_data, *p2_data, *u_data, *exp1_data, *exp2_data; | ||
849 | opaque *all_data = NULL, *p; | ||
850 | mpi_t exp1 = NULL, exp2 = NULL, q1 = NULL, p1 = NULL, u = NULL; | ||
851 | opaque null = '\0'; | ||
852 | |||
853 | /* Read all the sizes */ | ||
854 | total = 0; | ||
855 | for (i = 0; i < 5; i++) | ||
856 | { | ||
857 | _gnutls_mpi_print_lz (NULL, &size[i], params[i]); | ||
858 | total += size[i]; | ||
859 | } | ||
860 | |||
861 | /* Now generate exp1 and exp2 | ||
862 | */ | ||
863 | exp1 = _gnutls_mpi_salloc_like (params[0]); /* like modulus */ | ||
864 | if (exp1 == NULL) | ||
865 | { | ||
866 | gnutls_assert (); | ||
867 | result = GNUTLS_E_MEMORY_ERROR; | ||
868 | goto cleanup; | ||
869 | } | ||
870 | |||
871 | exp2 = _gnutls_mpi_salloc_like (params[0]); | ||
872 | if (exp2 == NULL) | ||
873 | { | ||
874 | gnutls_assert (); | ||
875 | result = GNUTLS_E_MEMORY_ERROR; | ||
876 | goto cleanup; | ||
877 | } | ||
878 | |||
879 | q1 = _gnutls_mpi_salloc_like (params[4]); | ||
880 | if (q1 == NULL) | ||
881 | { | ||
882 | gnutls_assert (); | ||
883 | result = GNUTLS_E_MEMORY_ERROR; | ||
884 | goto cleanup; | ||
885 | } | ||
886 | |||
887 | p1 = _gnutls_mpi_salloc_like (params[3]); | ||
888 | if (p1 == NULL) | ||
889 | { | ||
890 | gnutls_assert (); | ||
891 | result = GNUTLS_E_MEMORY_ERROR; | ||
892 | goto cleanup; | ||
893 | } | ||
894 | |||
895 | u = _gnutls_mpi_salloc_like (params[3]); | ||
896 | if (u == NULL) | ||
897 | { | ||
898 | gnutls_assert (); | ||
899 | result = GNUTLS_E_MEMORY_ERROR; | ||
900 | goto cleanup; | ||
901 | } | ||
902 | |||
903 | _gnutls_mpi_invm (u, params[4], params[3]); | ||
904 | /* inverse of q mod p */ | ||
905 | _gnutls_mpi_print_lz (NULL, &size[5], u); | ||
906 | total += size[5]; | ||
907 | |||
908 | _gnutls_mpi_sub_ui (p1, params[3], 1); | ||
909 | _gnutls_mpi_sub_ui (q1, params[4], 1); | ||
910 | |||
911 | _gnutls_mpi_mod (exp1, params[2], p1); | ||
912 | _gnutls_mpi_mod (exp2, params[2], q1); | ||
913 | |||
914 | /* calculate exp's size */ | ||
915 | _gnutls_mpi_print_lz (NULL, &size[6], exp1); | ||
916 | total += size[6]; | ||
917 | |||
918 | _gnutls_mpi_print_lz (NULL, &size[7], exp2); | ||
919 | total += size[7]; | ||
920 | |||
921 | /* Encoding phase. | ||
922 | * allocate data enough to hold everything | ||
923 | */ | ||
924 | all_data = gnutls_secure_malloc (total); | ||
925 | if (all_data == NULL) | ||
926 | { | ||
927 | gnutls_assert (); | ||
928 | result = GNUTLS_E_MEMORY_ERROR; | ||
929 | goto cleanup; | ||
930 | } | ||
931 | |||
932 | p = all_data; | ||
933 | m_data = p; | ||
934 | p += size[0]; | ||
935 | pube_data = p; | ||
936 | p += size[1]; | ||
937 | prie_data = p; | ||
938 | p += size[2]; | ||
939 | p1_data = p; | ||
940 | p += size[3]; | ||
941 | p2_data = p; | ||
942 | p += size[4]; | ||
943 | u_data = p; | ||
944 | p += size[5]; | ||
945 | exp1_data = p; | ||
946 | p += size[6]; | ||
947 | exp2_data = p; | ||
948 | |||
949 | _gnutls_mpi_print_lz (m_data, &size[0], params[0]); | ||
950 | _gnutls_mpi_print_lz (pube_data, &size[1], params[1]); | ||
951 | _gnutls_mpi_print_lz (prie_data, &size[2], params[2]); | ||
952 | _gnutls_mpi_print_lz (p1_data, &size[3], params[3]); | ||
953 | _gnutls_mpi_print_lz (p2_data, &size[4], params[4]); | ||
954 | _gnutls_mpi_print_lz (u_data, &size[5], u); | ||
955 | _gnutls_mpi_print_lz (exp1_data, &size[6], exp1); | ||
956 | _gnutls_mpi_print_lz (exp2_data, &size[7], exp2); | ||
957 | |||
958 | /* Ok. Now we have the data. Create the asn1 structures | ||
959 | */ | ||
960 | |||
961 | if ((result = | ||
962 | asn1_create_element (_gnutls_get_gnutls_asn (), "GNUTLS.RSAPrivateKey", | ||
963 | c2)) != ASN1_SUCCESS) | ||
964 | { | ||
965 | gnutls_assert (); | ||
966 | result = _gnutls_asn2err (result); | ||
967 | goto cleanup; | ||
968 | } | ||
969 | |||
970 | /* Write PRIME | ||
971 | */ | ||
972 | if ((result = asn1_write_value (*c2, "modulus", m_data, size[0])) | ||
973 | != ASN1_SUCCESS) | ||
974 | { | ||
975 | gnutls_assert (); | ||
976 | result = _gnutls_asn2err (result); | ||
977 | goto cleanup; | ||
978 | } | ||
979 | |||
980 | if ((result = asn1_write_value (*c2, "publicExponent", pube_data, size[1])) | ||
981 | != ASN1_SUCCESS) | ||
982 | { | ||
983 | gnutls_assert (); | ||
984 | result = _gnutls_asn2err (result); | ||
985 | goto cleanup; | ||
986 | } | ||
987 | |||
988 | if ((result = asn1_write_value (*c2, "privateExponent", prie_data, size[2])) | ||
989 | != ASN1_SUCCESS) | ||
990 | { | ||
991 | gnutls_assert (); | ||
992 | result = _gnutls_asn2err (result); | ||
993 | goto cleanup; | ||
994 | } | ||
995 | |||
996 | if ((result = asn1_write_value (*c2, "prime1", p1_data, size[3])) | ||
997 | != ASN1_SUCCESS) | ||
998 | { | ||
999 | gnutls_assert (); | ||
1000 | result = _gnutls_asn2err (result); | ||
1001 | goto cleanup; | ||
1002 | } | ||
1003 | |||
1004 | if ((result = asn1_write_value (*c2, "prime2", p2_data, size[4])) | ||
1005 | != ASN1_SUCCESS) | ||
1006 | { | ||
1007 | gnutls_assert (); | ||
1008 | result = _gnutls_asn2err (result); | ||
1009 | goto cleanup; | ||
1010 | } | ||
1011 | |||
1012 | if ((result = asn1_write_value (*c2, "exponent1", exp1_data, size[6])) | ||
1013 | != ASN1_SUCCESS) | ||
1014 | { | ||
1015 | gnutls_assert (); | ||
1016 | result = _gnutls_asn2err (result); | ||
1017 | goto cleanup; | ||
1018 | } | ||
1019 | |||
1020 | if ((result = asn1_write_value (*c2, "exponent2", exp2_data, size[7])) | ||
1021 | != ASN1_SUCCESS) | ||
1022 | { | ||
1023 | gnutls_assert (); | ||
1024 | result = _gnutls_asn2err (result); | ||
1025 | goto cleanup; | ||
1026 | } | ||
1027 | |||
1028 | if ((result = asn1_write_value (*c2, "coefficient", u_data, size[5])) | ||
1029 | != ASN1_SUCCESS) | ||
1030 | { | ||
1031 | gnutls_assert (); | ||
1032 | result = _gnutls_asn2err (result); | ||
1033 | goto cleanup; | ||
1034 | } | ||
1035 | |||
1036 | _gnutls_mpi_release (&exp1); | ||
1037 | _gnutls_mpi_release (&exp2); | ||
1038 | _gnutls_mpi_release (&q1); | ||
1039 | _gnutls_mpi_release (&p1); | ||
1040 | _gnutls_mpi_release (&u); | ||
1041 | gnutls_free (all_data); | ||
1042 | |||
1043 | if ((result = asn1_write_value (*c2, "otherPrimeInfos", | ||
1044 | NULL, 0)) != ASN1_SUCCESS) | ||
1045 | { | ||
1046 | gnutls_assert (); | ||
1047 | result = _gnutls_asn2err (result); | ||
1048 | goto cleanup; | ||
1049 | } | ||
1050 | |||
1051 | if ((result = asn1_write_value (*c2, "version", &null, 1)) != ASN1_SUCCESS) | ||
1052 | { | ||
1053 | gnutls_assert (); | ||
1054 | result = _gnutls_asn2err (result); | ||
1055 | goto cleanup; | ||
1056 | } | ||
1057 | |||
1058 | return 0; | ||
1059 | |||
1060 | cleanup:_gnutls_mpi_release (&u); | ||
1061 | _gnutls_mpi_release (&exp1); | ||
1062 | _gnutls_mpi_release (&exp2); | ||
1063 | _gnutls_mpi_release (&q1); | ||
1064 | _gnutls_mpi_release (&p1); | ||
1065 | asn1_delete_structure (c2); | ||
1066 | gnutls_free (all_data); | ||
1067 | |||
1068 | return result; | ||
1069 | } | ||
1070 | |||
1071 | /* Encodes the DSA parameters into an ASN.1 DSAPrivateKey structure. | ||
1072 | */ | ||
1073 | int | ||
1074 | _gnutls_asn1_encode_dsa (ASN1_TYPE * c2, mpi_t * params) | ||
1075 | { | ||
1076 | int result, i; | ||
1077 | size_t size[DSA_PRIVATE_PARAMS], total; | ||
1078 | opaque *p_data, *q_data, *g_data, *x_data, *y_data; | ||
1079 | opaque *all_data = NULL, *p; | ||
1080 | opaque null = '\0'; | ||
1081 | |||
1082 | /* Read all the sizes */ | ||
1083 | total = 0; | ||
1084 | for (i = 0; i < DSA_PRIVATE_PARAMS; i++) | ||
1085 | { | ||
1086 | _gnutls_mpi_print_lz (NULL, &size[i], params[i]); | ||
1087 | total += size[i]; | ||
1088 | } | ||
1089 | |||
1090 | /* Encoding phase. | ||
1091 | * allocate data enough to hold everything | ||
1092 | */ | ||
1093 | all_data = gnutls_secure_malloc (total); | ||
1094 | if (all_data == NULL) | ||
1095 | { | ||
1096 | gnutls_assert (); | ||
1097 | result = GNUTLS_E_MEMORY_ERROR; | ||
1098 | goto cleanup; | ||
1099 | } | ||
1100 | |||
1101 | p = all_data; | ||
1102 | p_data = p; | ||
1103 | p += size[0]; | ||
1104 | q_data = p; | ||
1105 | p += size[1]; | ||
1106 | g_data = p; | ||
1107 | p += size[2]; | ||
1108 | y_data = p; | ||
1109 | p += size[3]; | ||
1110 | x_data = p; | ||
1111 | |||
1112 | _gnutls_mpi_print_lz (p_data, &size[0], params[0]); | ||
1113 | _gnutls_mpi_print_lz (q_data, &size[1], params[1]); | ||
1114 | _gnutls_mpi_print_lz (g_data, &size[2], params[2]); | ||
1115 | _gnutls_mpi_print_lz (y_data, &size[3], params[3]); | ||
1116 | _gnutls_mpi_print_lz (x_data, &size[4], params[4]); | ||
1117 | |||
1118 | /* Ok. Now we have the data. Create the asn1 structures | ||
1119 | */ | ||
1120 | |||
1121 | if ((result = | ||
1122 | asn1_create_element (_gnutls_get_gnutls_asn (), "GNUTLS.DSAPrivateKey", | ||
1123 | c2)) != ASN1_SUCCESS) | ||
1124 | { | ||
1125 | gnutls_assert (); | ||
1126 | result = _gnutls_asn2err (result); | ||
1127 | goto cleanup; | ||
1128 | } | ||
1129 | |||
1130 | /* Write PRIME | ||
1131 | */ | ||
1132 | if ((result = asn1_write_value (*c2, "p", p_data, size[0])) != ASN1_SUCCESS) | ||
1133 | { | ||
1134 | gnutls_assert (); | ||
1135 | result = _gnutls_asn2err (result); | ||
1136 | goto cleanup; | ||
1137 | } | ||
1138 | |||
1139 | if ((result = asn1_write_value (*c2, "q", q_data, size[1])) != ASN1_SUCCESS) | ||
1140 | { | ||
1141 | gnutls_assert (); | ||
1142 | result = _gnutls_asn2err (result); | ||
1143 | goto cleanup; | ||
1144 | } | ||
1145 | |||
1146 | if ((result = asn1_write_value (*c2, "g", g_data, size[2])) != ASN1_SUCCESS) | ||
1147 | { | ||
1148 | gnutls_assert (); | ||
1149 | result = _gnutls_asn2err (result); | ||
1150 | goto cleanup; | ||
1151 | } | ||
1152 | |||
1153 | if ((result = asn1_write_value (*c2, "Y", y_data, size[3])) != ASN1_SUCCESS) | ||
1154 | { | ||
1155 | gnutls_assert (); | ||
1156 | result = _gnutls_asn2err (result); | ||
1157 | goto cleanup; | ||
1158 | } | ||
1159 | |||
1160 | if ((result = | ||
1161 | asn1_write_value (*c2, "priv", x_data, size[4])) != ASN1_SUCCESS) | ||
1162 | { | ||
1163 | gnutls_assert (); | ||
1164 | result = _gnutls_asn2err (result); | ||
1165 | goto cleanup; | ||
1166 | } | ||
1167 | |||
1168 | gnutls_free (all_data); | ||
1169 | |||
1170 | if ((result = asn1_write_value (*c2, "version", &null, 1)) != ASN1_SUCCESS) | ||
1171 | { | ||
1172 | gnutls_assert (); | ||
1173 | result = _gnutls_asn2err (result); | ||
1174 | goto cleanup; | ||
1175 | } | ||
1176 | |||
1177 | return 0; | ||
1178 | |||
1179 | cleanup:asn1_delete_structure (c2); | ||
1180 | gnutls_free (all_data); | ||
1181 | |||
1182 | return result; | ||
1183 | } | ||
1184 | |||
1185 | /** | ||
1186 | * gnutls_x509_privkey_generate - This function will generate a private key | ||
1187 | * @key: should contain a gnutls_x509_privkey_t structure | ||
1188 | * @algo: is one of RSA or DSA. | ||
1189 | * @bits: the size of the modulus | ||
1190 | * @flags: unused for now. Must be 0. | ||
1191 | * | ||
1192 | * This function will generate a random private key. Note that | ||
1193 | * this function must be called on an empty private key. | ||
1194 | * | ||
1195 | * Returns 0 on success or a negative value on error. | ||
1196 | * | ||
1197 | **/ | ||
1198 | int | ||
1199 | gnutls_x509_privkey_generate (gnutls_x509_privkey_t key, | ||
1200 | gnutls_pk_algorithm_t algo, | ||
1201 | unsigned int bits, unsigned int flags) | ||
1202 | { | ||
1203 | int ret, params_len; | ||
1204 | int i; | ||
1205 | |||
1206 | if (key == NULL) | ||
1207 | { | ||
1208 | gnutls_assert (); | ||
1209 | return GNUTLS_E_INVALID_REQUEST; | ||
1210 | } | ||
1211 | |||
1212 | switch (algo) | ||
1213 | { | ||
1214 | case GNUTLS_PK_RSA: | ||
1215 | ret = _gnutls_rsa_generate_params (key->params, ¶ms_len, bits); | ||
1216 | if (ret < 0) | ||
1217 | { | ||
1218 | gnutls_assert (); | ||
1219 | return ret; | ||
1220 | } | ||
1221 | |||
1222 | if (!key->crippled) | ||
1223 | { | ||
1224 | ret = _gnutls_asn1_encode_rsa (&key->key, key->params); | ||
1225 | if (ret < 0) | ||
1226 | { | ||
1227 | gnutls_assert (); | ||
1228 | goto cleanup; | ||
1229 | } | ||
1230 | } | ||
1231 | |||
1232 | key->params_size = params_len; | ||
1233 | key->pk_algorithm = GNUTLS_PK_RSA; | ||
1234 | |||
1235 | break; | ||
1236 | default: | ||
1237 | gnutls_assert (); | ||
1238 | return GNUTLS_E_INVALID_REQUEST; | ||
1239 | } | ||
1240 | |||
1241 | return 0; | ||
1242 | |||
1243 | cleanup:key->pk_algorithm = GNUTLS_PK_UNKNOWN; | ||
1244 | key->params_size = 0; | ||
1245 | for (i = 0; i < params_len; i++) | ||
1246 | _gnutls_mpi_release (&key->params[i]); | ||
1247 | |||
1248 | return ret; | ||
1249 | } | ||
1250 | |||
1251 | /** | ||
1252 | * gnutls_x509_privkey_get_key_id - Return unique ID of the key's parameters | ||
1253 | * @key: Holds the key | ||
1254 | * @flags: should be 0 for now | ||
1255 | * @output_data: will contain the key ID | ||
1256 | * @output_data_size: holds the size of output_data (and will be | ||
1257 | * replaced by the actual size of parameters) | ||
1258 | * | ||
1259 | * This function will return a unique ID the depends on the public key | ||
1260 | * parameters. This ID can be used in checking whether a certificate | ||
1261 | * corresponds to the given key. | ||
1262 | * | ||
1263 | * If the buffer provided is not long enough to hold the output, then | ||
1264 | * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will | ||
1265 | * be returned. The output will normally be a SHA-1 hash output, | ||
1266 | * which is 20 bytes. | ||
1267 | * | ||
1268 | * Return value: In case of failure a negative value will be | ||
1269 | * returned, and 0 on success. | ||
1270 | * | ||
1271 | **/ | ||
1272 | int | ||
1273 | gnutls_x509_privkey_get_key_id (gnutls_x509_privkey_t key, | ||
1274 | unsigned int flags, | ||
1275 | unsigned char *output_data, | ||
1276 | size_t * output_data_size) | ||
1277 | { | ||
1278 | int result; | ||
1279 | GNUTLS_HASH_HANDLE hd; | ||
1280 | gnutls_datum_t der = { NULL, | ||
1281 | 0 | ||
1282 | }; | ||
1283 | |||
1284 | if (key == NULL || key->crippled) | ||
1285 | { | ||
1286 | gnutls_assert (); | ||
1287 | return GNUTLS_E_INVALID_REQUEST; | ||
1288 | } | ||
1289 | |||
1290 | if (*output_data_size < 20) | ||
1291 | { | ||
1292 | gnutls_assert (); | ||
1293 | *output_data_size = 20; | ||
1294 | return GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
1295 | } | ||
1296 | |||
1297 | if (key->pk_algorithm == GNUTLS_PK_RSA) | ||
1298 | { | ||
1299 | result = _gnutls_x509_write_rsa_params (key->params, key->params_size, | ||
1300 | &der); | ||
1301 | if (result < 0) | ||
1302 | { | ||
1303 | gnutls_assert (); | ||
1304 | goto cleanup; | ||
1305 | } | ||
1306 | } | ||
1307 | else | ||
1308 | return GNUTLS_E_INTERNAL_ERROR; | ||
1309 | |||
1310 | hd = _gnutls_hash_init (GNUTLS_MAC_SHA1); | ||
1311 | if (hd == GNUTLS_HASH_FAILED) | ||
1312 | { | ||
1313 | gnutls_assert (); | ||
1314 | result = GNUTLS_E_INTERNAL_ERROR; | ||
1315 | goto cleanup; | ||
1316 | } | ||
1317 | |||
1318 | _gnutls_hash (hd, der.data, der.size); | ||
1319 | |||
1320 | _gnutls_hash_deinit (hd, output_data); | ||
1321 | *output_data_size = 20; | ||
1322 | |||
1323 | result = 0; | ||
1324 | |||
1325 | cleanup: | ||
1326 | |||
1327 | _gnutls_free_datum (&der); | ||
1328 | return result; | ||
1329 | } | ||
1330 | |||
1331 | #ifdef ENABLE_PKI | ||
1332 | |||
1333 | /** | ||
1334 | * gnutls_x509_privkey_sign_data - This function will sign the given data using the private key params | ||
1335 | * @key: Holds the key | ||
1336 | * @digest: should be MD5 or SHA1 | ||
1337 | * @flags: should be 0 for now | ||
1338 | * @data: holds the data to be signed | ||
1339 | * @signature: will contain the signature | ||
1340 | * @signature_size: holds the size of signature (and will be replaced | ||
1341 | * by the new size) | ||
1342 | * | ||
1343 | * This function will sign the given data using a signature algorithm | ||
1344 | * supported by the private key. Signature algorithms are always used | ||
1345 | * together with a hash functions. Different hash functions may be | ||
1346 | * used for the RSA algorithm, but only SHA-1 for the DSA keys. | ||
1347 | * | ||
1348 | * If the buffer provided is not long enough to hold the output, then | ||
1349 | * *signature_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will | ||
1350 | * be returned. | ||
1351 | * | ||
1352 | * In case of failure a negative value will be returned, and | ||
1353 | * 0 on success. | ||
1354 | * | ||
1355 | **/ | ||
1356 | int | ||
1357 | gnutls_x509_privkey_sign_data (gnutls_x509_privkey_t key, | ||
1358 | gnutls_digest_algorithm_t digest, | ||
1359 | unsigned int flags, | ||
1360 | const gnutls_datum_t * data, | ||
1361 | void *signature, size_t * signature_size) | ||
1362 | { | ||
1363 | int result; | ||
1364 | gnutls_datum_t sig = { NULL, 0 }; | ||
1365 | |||
1366 | if (key == NULL) | ||
1367 | { | ||
1368 | gnutls_assert (); | ||
1369 | return GNUTLS_E_INVALID_REQUEST; | ||
1370 | } | ||
1371 | |||
1372 | result = _gnutls_x509_sign (data, digest, key, &sig); | ||
1373 | if (result < 0) | ||
1374 | { | ||
1375 | gnutls_assert (); | ||
1376 | return result; | ||
1377 | } | ||
1378 | |||
1379 | if (*signature_size < sig.size) | ||
1380 | { | ||
1381 | *signature_size = sig.size; | ||
1382 | _gnutls_free_datum (&sig); | ||
1383 | return GNUTLS_E_SHORT_MEMORY_BUFFER; | ||
1384 | } | ||
1385 | |||
1386 | *signature_size = sig.size; | ||
1387 | memcpy (signature, sig.data, sig.size); | ||
1388 | |||
1389 | _gnutls_free_datum (&sig); | ||
1390 | |||
1391 | return 0; | ||
1392 | } | ||
1393 | |||
1394 | /** | ||
1395 | * gnutls_x509_privkey_sign_hash - This function will sign the given data using the private key params | ||
1396 | * @key: Holds the key | ||
1397 | * @hash: holds the data to be signed | ||
1398 | * @signature: will contain newly allocated signature | ||
1399 | * | ||
1400 | * This function will sign the given hash using the private key. | ||
1401 | * | ||
1402 | * Return value: In case of failure a negative value will be returned, | ||
1403 | * and 0 on success. | ||
1404 | **/ | ||
1405 | int | ||
1406 | gnutls_x509_privkey_sign_hash (gnutls_x509_privkey_t key, | ||
1407 | const gnutls_datum_t * hash, | ||
1408 | gnutls_datum_t * signature) | ||
1409 | { | ||
1410 | int result; | ||
1411 | |||
1412 | if (key == NULL) | ||
1413 | { | ||
1414 | gnutls_assert (); | ||
1415 | return GNUTLS_E_INVALID_REQUEST; | ||
1416 | } | ||
1417 | |||
1418 | result = _gnutls_sign (key->pk_algorithm, key->params, | ||
1419 | key->params_size, hash, signature); | ||
1420 | if (result < 0) | ||
1421 | { | ||
1422 | gnutls_assert (); | ||
1423 | return result; | ||
1424 | } | ||
1425 | |||
1426 | return 0; | ||
1427 | } | ||
1428 | |||
1429 | /** | ||
1430 | * gnutls_x509_privkey_verify_data - This function will verify the given signed data. | ||
1431 | * @key: Holds the key | ||
1432 | * @flags: should be 0 for now | ||
1433 | * @data: holds the data to be signed | ||
1434 | * @signature: contains the signature | ||
1435 | * | ||
1436 | * This function will verify the given signed data, using the parameters in the | ||
1437 | * private key. | ||
1438 | * | ||
1439 | * In case of a verification failure 0 is returned, and | ||
1440 | * 1 on success. | ||
1441 | * | ||
1442 | **/ | ||
1443 | int | ||
1444 | gnutls_x509_privkey_verify_data (gnutls_x509_privkey_t key, | ||
1445 | unsigned int flags, | ||
1446 | const gnutls_datum_t * data, | ||
1447 | const gnutls_datum_t * signature) | ||
1448 | { | ||
1449 | int result; | ||
1450 | |||
1451 | if (key == NULL) | ||
1452 | { | ||
1453 | gnutls_assert (); | ||
1454 | return GNUTLS_E_INVALID_REQUEST; | ||
1455 | } | ||
1456 | |||
1457 | result = _gnutls_x509_privkey_verify_signature (data, signature, key); | ||
1458 | if (result < 0) | ||
1459 | { | ||
1460 | gnutls_assert (); | ||
1461 | return 0; | ||
1462 | } | ||
1463 | |||
1464 | return result; | ||
1465 | } | ||
1466 | |||
1467 | /** | ||
1468 | * gnutls_x509_privkey_fix - This function will recalculate some parameters of the key. | ||
1469 | * @key: Holds the key | ||
1470 | * | ||
1471 | * This function will recalculate the secondary parameters in a key. | ||
1472 | * In RSA keys, this can be the coefficient and exponent1,2. | ||
1473 | * | ||
1474 | * Return value: In case of failure a negative value will be | ||
1475 | * returned, and 0 on success. | ||
1476 | * | ||
1477 | **/ | ||
1478 | int | ||
1479 | gnutls_x509_privkey_fix (gnutls_x509_privkey_t key) | ||
1480 | { | ||
1481 | int ret; | ||
1482 | |||
1483 | if (key == NULL) | ||
1484 | { | ||
1485 | gnutls_assert (); | ||
1486 | return GNUTLS_E_INVALID_REQUEST; | ||
1487 | } | ||
1488 | |||
1489 | if (!key->crippled) | ||
1490 | asn1_delete_structure (&key->key); | ||
1491 | switch (key->pk_algorithm) | ||
1492 | { | ||
1493 | case GNUTLS_PK_RSA: | ||
1494 | ret = _gnutls_asn1_encode_rsa (&key->key, key->params); | ||
1495 | if (ret < 0) | ||
1496 | { | ||
1497 | gnutls_assert (); | ||
1498 | return ret; | ||
1499 | } | ||
1500 | break; | ||
1501 | default: | ||
1502 | gnutls_assert (); | ||
1503 | return GNUTLS_E_INVALID_REQUEST; | ||
1504 | } | ||
1505 | |||
1506 | return 0; | ||
1507 | } | ||
1508 | |||
1509 | #endif | ||
diff --git a/src/daemon/https/x509/x509_verify.c b/src/daemon/https/x509/x509_verify.c new file mode 100644 index 00000000..f01fed9d --- /dev/null +++ b/src/daemon/https/x509/x509_verify.c | |||
@@ -0,0 +1,1037 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | /* All functions which relate to X.509 certificate verification stuff are | ||
26 | * included here | ||
27 | */ | ||
28 | |||
29 | #include <gnutls_int.h> | ||
30 | #include <gnutls_errors.h> | ||
31 | #include <gnutls_cert.h> | ||
32 | #include <libtasn1.h> | ||
33 | #include <gnutls_global.h> | ||
34 | #include <gnutls_num.h> /* MAX */ | ||
35 | #include <gnutls_sig.h> | ||
36 | #include <gnutls_str.h> | ||
37 | #include <gnutls_datum.h> | ||
38 | #include <dn.h> | ||
39 | #include <x509.h> | ||
40 | #include <mpi.h> | ||
41 | #include <common.h> | ||
42 | #include <verify.h> | ||
43 | |||
44 | static int _gnutls_verify_certificate2 (gnutls_x509_crt_t cert, | ||
45 | const gnutls_x509_crt_t * trusted_cas, | ||
46 | int tcas_size, | ||
47 | unsigned int flags, | ||
48 | unsigned int *output); | ||
49 | int _gnutls_x509_verify_signature (const gnutls_datum_t * signed_data, | ||
50 | const gnutls_datum_t * signature, | ||
51 | gnutls_x509_crt_t issuer); | ||
52 | |||
53 | static | ||
54 | int is_crl_issuer (gnutls_x509_crl_t crl, gnutls_x509_crt_t issuer_cert); | ||
55 | static int _gnutls_verify_crl2 (gnutls_x509_crl_t crl, | ||
56 | const gnutls_x509_crt_t * trusted_cas, | ||
57 | int tcas_size, | ||
58 | unsigned int flags, unsigned int *output); | ||
59 | |||
60 | /* Checks if the issuer of a certificate is a | ||
61 | * Certificate Authority, or if the certificate is the same | ||
62 | * as the issuer (and therefore it doesn't need to be a CA). | ||
63 | * | ||
64 | * Returns true or false, if the issuer is a CA, | ||
65 | * or not. | ||
66 | */ | ||
67 | static int | ||
68 | check_if_ca (gnutls_x509_crt_t cert, | ||
69 | gnutls_x509_crt_t issuer, unsigned int flags) | ||
70 | { | ||
71 | gnutls_datum_t cert_signed_data = { NULL, | ||
72 | 0 | ||
73 | }; | ||
74 | gnutls_datum_t issuer_signed_data = { NULL, | ||
75 | 0 | ||
76 | }; | ||
77 | gnutls_datum_t cert_signature = { NULL, | ||
78 | 0 | ||
79 | }; | ||
80 | gnutls_datum_t issuer_signature = { NULL, | ||
81 | 0 | ||
82 | }; | ||
83 | int result; | ||
84 | |||
85 | /* Check if the issuer is the same with the | ||
86 | * certificate. This is added in order for trusted | ||
87 | * certificates to be able to verify themselves. | ||
88 | */ | ||
89 | |||
90 | result = _gnutls_x509_get_signed_data (issuer->cert, "tbsCertificate", | ||
91 | &issuer_signed_data); | ||
92 | if (result < 0) | ||
93 | { | ||
94 | gnutls_assert (); | ||
95 | goto cleanup; | ||
96 | } | ||
97 | |||
98 | result = _gnutls_x509_get_signed_data (cert->cert, "tbsCertificate", | ||
99 | &cert_signed_data); | ||
100 | if (result < 0) | ||
101 | { | ||
102 | gnutls_assert (); | ||
103 | goto cleanup; | ||
104 | } | ||
105 | |||
106 | result = _gnutls_x509_get_signature (issuer->cert, "signature", | ||
107 | &issuer_signature); | ||
108 | if (result < 0) | ||
109 | { | ||
110 | gnutls_assert (); | ||
111 | goto cleanup; | ||
112 | } | ||
113 | |||
114 | result = | ||
115 | _gnutls_x509_get_signature (cert->cert, "signature", &cert_signature); | ||
116 | if (result < 0) | ||
117 | { | ||
118 | gnutls_assert (); | ||
119 | goto cleanup; | ||
120 | } | ||
121 | |||
122 | /* If the subject certificate is the same as the issuer | ||
123 | * return true. | ||
124 | */ | ||
125 | if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_SAME)) | ||
126 | if (cert_signed_data.size == issuer_signed_data.size) | ||
127 | { | ||
128 | if ((memcmp (cert_signed_data.data, issuer_signed_data.data, | ||
129 | cert_signed_data.size) == 0) && (cert_signature.size | ||
130 | == | ||
131 | issuer_signature.size) | ||
132 | && | ||
133 | (memcmp | ||
134 | (cert_signature.data, issuer_signature.data, | ||
135 | cert_signature.size) == 0)) | ||
136 | { | ||
137 | result = 1; | ||
138 | goto cleanup; | ||
139 | } | ||
140 | } | ||
141 | |||
142 | if (gnutls_x509_crt_get_ca_status (issuer, NULL) == 1) | ||
143 | { | ||
144 | result = 1; | ||
145 | goto cleanup; | ||
146 | } | ||
147 | else | ||
148 | gnutls_assert (); | ||
149 | |||
150 | result = 0; | ||
151 | |||
152 | cleanup:_gnutls_free_datum (&cert_signed_data); | ||
153 | _gnutls_free_datum (&issuer_signed_data); | ||
154 | _gnutls_free_datum (&cert_signature); | ||
155 | _gnutls_free_datum (&issuer_signature); | ||
156 | return result; | ||
157 | } | ||
158 | |||
159 | /* This function checks if 'certs' issuer is 'issuer_cert'. | ||
160 | * This does a straight (DER) compare of the issuer/subject fields in | ||
161 | * the given certificates. | ||
162 | * | ||
163 | * Returns 1 if they match and zero if they don't match. Otherwise | ||
164 | * a negative value is returned to indicate error. | ||
165 | */ | ||
166 | static int | ||
167 | is_issuer (gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer_cert) | ||
168 | { | ||
169 | gnutls_datum_t dn1 = { NULL, | ||
170 | 0 | ||
171 | }, dn2 = | ||
172 | { | ||
173 | NULL, 0}; | ||
174 | int ret; | ||
175 | |||
176 | ret = gnutls_x509_crt_get_raw_issuer_dn (cert, &dn1); | ||
177 | if (ret < 0) | ||
178 | { | ||
179 | gnutls_assert (); | ||
180 | goto cleanup; | ||
181 | } | ||
182 | |||
183 | ret = gnutls_x509_crt_get_raw_dn (issuer_cert, &dn2); | ||
184 | if (ret < 0) | ||
185 | { | ||
186 | gnutls_assert (); | ||
187 | goto cleanup; | ||
188 | } | ||
189 | |||
190 | ret = _gnutls_x509_compare_raw_dn (&dn1, &dn2); | ||
191 | |||
192 | cleanup:_gnutls_free_datum (&dn1); | ||
193 | _gnutls_free_datum (&dn2); | ||
194 | return ret; | ||
195 | |||
196 | } | ||
197 | |||
198 | static inline gnutls_x509_crt_t | ||
199 | find_issuer (gnutls_x509_crt_t cert, | ||
200 | const gnutls_x509_crt_t * trusted_cas, int tcas_size) | ||
201 | { | ||
202 | int i; | ||
203 | |||
204 | /* this is serial search. | ||
205 | */ | ||
206 | |||
207 | for (i = 0; i < tcas_size; i++) | ||
208 | { | ||
209 | if (is_issuer (cert, trusted_cas[i]) == 1) | ||
210 | return trusted_cas[i]; | ||
211 | } | ||
212 | |||
213 | gnutls_assert (); | ||
214 | return NULL; | ||
215 | } | ||
216 | |||
217 | /* | ||
218 | * Verifies the given certificate again a certificate list of | ||
219 | * trusted CAs. | ||
220 | * | ||
221 | * Returns only 0 or 1. If 1 it means that the certificate | ||
222 | * was successfuly verified. | ||
223 | * | ||
224 | * 'flags': an OR of the gnutls_certificate_verify_flags enumeration. | ||
225 | * | ||
226 | * Output will hold some extra information about the verification | ||
227 | * procedure. | ||
228 | */ | ||
229 | static int | ||
230 | _gnutls_verify_certificate2 (gnutls_x509_crt_t cert, | ||
231 | const gnutls_x509_crt_t * trusted_cas, | ||
232 | int tcas_size, | ||
233 | unsigned int flags, unsigned int *output) | ||
234 | { | ||
235 | gnutls_datum_t cert_signed_data = { NULL, | ||
236 | 0 | ||
237 | }; | ||
238 | gnutls_datum_t cert_signature = { NULL, | ||
239 | 0 | ||
240 | }; | ||
241 | gnutls_x509_crt_t issuer; | ||
242 | int ret, issuer_version, result; | ||
243 | |||
244 | if (output) | ||
245 | *output = 0; | ||
246 | |||
247 | if (tcas_size >= 1) | ||
248 | issuer = find_issuer (cert, trusted_cas, tcas_size); | ||
249 | else | ||
250 | { | ||
251 | gnutls_assert (); | ||
252 | if (output) | ||
253 | *output |= GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID; | ||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | /* issuer is not in trusted certificate | ||
258 | * authorities. | ||
259 | */ | ||
260 | if (issuer == NULL) | ||
261 | { | ||
262 | if (output) | ||
263 | *output |= GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID; | ||
264 | gnutls_assert (); | ||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | issuer_version = gnutls_x509_crt_get_version (issuer); | ||
269 | if (issuer_version < 0) | ||
270 | { | ||
271 | gnutls_assert (); | ||
272 | return issuer_version; | ||
273 | } | ||
274 | |||
275 | if (!(flags & GNUTLS_VERIFY_DISABLE_CA_SIGN) && !((flags | ||
276 | & | ||
277 | GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT) | ||
278 | && issuer_version == 1)) | ||
279 | { | ||
280 | if (check_if_ca (cert, issuer, flags) == 0) | ||
281 | { | ||
282 | gnutls_assert (); | ||
283 | if (output) | ||
284 | *output |= GNUTLS_CERT_SIGNER_NOT_CA | GNUTLS_CERT_INVALID; | ||
285 | return 0; | ||
286 | } | ||
287 | } | ||
288 | |||
289 | result = _gnutls_x509_get_signed_data (cert->cert, "tbsCertificate", | ||
290 | &cert_signed_data); | ||
291 | if (result < 0) | ||
292 | { | ||
293 | gnutls_assert (); | ||
294 | goto cleanup; | ||
295 | } | ||
296 | |||
297 | result = | ||
298 | _gnutls_x509_get_signature (cert->cert, "signature", &cert_signature); | ||
299 | if (result < 0) | ||
300 | { | ||
301 | gnutls_assert (); | ||
302 | goto cleanup; | ||
303 | } | ||
304 | |||
305 | ret = _gnutls_x509_verify_signature (&cert_signed_data, &cert_signature, | ||
306 | issuer); | ||
307 | if (ret < 0) | ||
308 | { | ||
309 | gnutls_assert (); | ||
310 | } | ||
311 | else if (ret == 0) | ||
312 | { | ||
313 | gnutls_assert (); | ||
314 | /* error. ignore it */ | ||
315 | if (output) | ||
316 | *output |= GNUTLS_CERT_INVALID; | ||
317 | ret = 0; | ||
318 | } | ||
319 | |||
320 | /* If the certificate is not self signed check if the algorithms | ||
321 | * used are secure. If the certificate is self signed it doesn't | ||
322 | * really matter. | ||
323 | */ | ||
324 | if (is_issuer (cert, cert) == 0) | ||
325 | { | ||
326 | int sigalg; | ||
327 | |||
328 | sigalg = gnutls_x509_crt_get_signature_algorithm (cert); | ||
329 | |||
330 | if (((sigalg == GNUTLS_SIGN_RSA_MD2) && !(flags | ||
331 | & | ||
332 | GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2)) | ||
333 | || ((sigalg == GNUTLS_SIGN_RSA_MD5) | ||
334 | && !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5))) | ||
335 | { | ||
336 | if (output) | ||
337 | *output |= GNUTLS_CERT_INSECURE_ALGORITHM | GNUTLS_CERT_INVALID; | ||
338 | } | ||
339 | } | ||
340 | |||
341 | result = ret; | ||
342 | |||
343 | cleanup:_gnutls_free_datum (&cert_signed_data); | ||
344 | _gnutls_free_datum (&cert_signature); | ||
345 | |||
346 | return result; | ||
347 | } | ||
348 | |||
349 | /** | ||
350 | * gnutls_x509_crt_check_issuer - This function checks if the certificate given has the given issuer | ||
351 | * @cert: is the certificate to be checked | ||
352 | * @issuer: is the certificate of a possible issuer | ||
353 | * | ||
354 | * This function will check if the given certificate was issued by the | ||
355 | * given issuer. It will return true (1) if the given certificate is issued | ||
356 | * by the given issuer, and false (0) if not. | ||
357 | * | ||
358 | * A negative value is returned in case of an error. | ||
359 | * | ||
360 | **/ | ||
361 | int | ||
362 | gnutls_x509_crt_check_issuer (gnutls_x509_crt_t cert, | ||
363 | gnutls_x509_crt_t issuer) | ||
364 | { | ||
365 | return is_issuer (cert, issuer); | ||
366 | } | ||
367 | |||
368 | /* The algorithm used is: | ||
369 | * 1. Check last certificate in the chain. If it is not verified return. | ||
370 | * 2. Check if any certificates in the chain are revoked. If yes return. | ||
371 | * 3. Try to verify the rest of certificates in the chain. If not verified return. | ||
372 | * 4. Return 0. | ||
373 | * | ||
374 | * Note that the return value is an OR of GNUTLS_CERT_* elements. | ||
375 | * | ||
376 | * This function verifies a X.509 certificate list. The certificate list should | ||
377 | * lead to a trusted CA in order to be trusted. | ||
378 | */ | ||
379 | static unsigned int | ||
380 | _gnutls_x509_verify_certificate (const gnutls_x509_crt_t * certificate_list, | ||
381 | int clist_size, | ||
382 | const gnutls_x509_crt_t * trusted_cas, | ||
383 | int tcas_size, | ||
384 | const gnutls_x509_crl_t * CRLs, | ||
385 | int crls_size, unsigned int flags) | ||
386 | { | ||
387 | int i = 0, ret; | ||
388 | unsigned int status = 0, output; | ||
389 | |||
390 | /* Verify the last certificate in the certificate path | ||
391 | * against the trusted CA certificate list. | ||
392 | * | ||
393 | * If no CAs are present returns CERT_INVALID. Thus works | ||
394 | * in self signed etc certificates. | ||
395 | */ | ||
396 | ret = _gnutls_verify_certificate2 (certificate_list[clist_size - 1], | ||
397 | trusted_cas, tcas_size, flags, &output); | ||
398 | |||
399 | if (ret == 0) | ||
400 | { | ||
401 | /* if the last certificate in the certificate | ||
402 | * list is invalid, then the certificate is not | ||
403 | * trusted. | ||
404 | */ | ||
405 | gnutls_assert (); | ||
406 | status |= output; | ||
407 | status |= GNUTLS_CERT_INVALID; | ||
408 | return status; | ||
409 | } | ||
410 | |||
411 | /* Check for revoked certificates in the chain | ||
412 | */ | ||
413 | #ifdef ENABLE_PKI | ||
414 | for (i = 0; i < clist_size; i++) | ||
415 | { | ||
416 | ret = gnutls_x509_crt_check_revocation (certificate_list[i], | ||
417 | CRLs, crls_size); | ||
418 | if (ret == 1) | ||
419 | { /* revoked */ | ||
420 | status |= GNUTLS_CERT_REVOKED; | ||
421 | status |= GNUTLS_CERT_INVALID; | ||
422 | return status; | ||
423 | } | ||
424 | } | ||
425 | #endif | ||
426 | |||
427 | /* Check if the last certificate in the path is self signed. | ||
428 | * In that case ignore it (a certificate is trusted only if it | ||
429 | * leads to a trusted party by us, not the server's). | ||
430 | */ | ||
431 | if (gnutls_x509_crt_check_issuer (certificate_list[clist_size - 1], | ||
432 | certificate_list[clist_size - 1]) > 0 | ||
433 | && clist_size > 0) | ||
434 | { | ||
435 | clist_size--; | ||
436 | } | ||
437 | |||
438 | /* Verify the certificate path (chain) | ||
439 | */ | ||
440 | for (i = clist_size - 1; i > 0; i--) | ||
441 | { | ||
442 | if (i - 1 < 0) | ||
443 | break; | ||
444 | |||
445 | /* note that here we disable this V1 CA flag. So that no version 1 | ||
446 | * certificates can exist in a supplied chain. | ||
447 | */ | ||
448 | if (!(flags & GNUTLS_VERIFY_ALLOW_ANY_X509_V1_CA_CRT)) | ||
449 | flags ^= GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT; | ||
450 | if ((ret = _gnutls_verify_certificate2 (certificate_list[i - 1], | ||
451 | &certificate_list[i], 1, flags, | ||
452 | NULL)) == 0) | ||
453 | { | ||
454 | status |= GNUTLS_CERT_INVALID; | ||
455 | return status; | ||
456 | } | ||
457 | } | ||
458 | |||
459 | return 0; | ||
460 | } | ||
461 | |||
462 | /* Reads the digest information. | ||
463 | * we use DER here, although we should use BER. It works fine | ||
464 | * anyway. | ||
465 | */ | ||
466 | static int | ||
467 | decode_ber_digest_info (const gnutls_datum_t * info, | ||
468 | gnutls_mac_algorithm_t * hash, | ||
469 | opaque * digest, int *digest_size) | ||
470 | { | ||
471 | ASN1_TYPE dinfo = ASN1_TYPE_EMPTY; | ||
472 | int result; | ||
473 | char str[1024]; | ||
474 | int len; | ||
475 | |||
476 | if ((result = asn1_create_element (_gnutls_get_gnutls_asn (), | ||
477 | "GNUTLS.DigestInfo", | ||
478 | &dinfo)) != ASN1_SUCCESS) | ||
479 | { | ||
480 | gnutls_assert (); | ||
481 | return _gnutls_asn2err (result); | ||
482 | } | ||
483 | |||
484 | result = asn1_der_decoding (&dinfo, info->data, info->size, NULL); | ||
485 | if (result != ASN1_SUCCESS) | ||
486 | { | ||
487 | gnutls_assert (); | ||
488 | asn1_delete_structure (&dinfo); | ||
489 | return _gnutls_asn2err (result); | ||
490 | } | ||
491 | |||
492 | len = sizeof (str) - 1; | ||
493 | result = asn1_read_value (dinfo, "digestAlgorithm.algorithm", str, &len); | ||
494 | if (result != ASN1_SUCCESS) | ||
495 | { | ||
496 | gnutls_assert (); | ||
497 | asn1_delete_structure (&dinfo); | ||
498 | return _gnutls_asn2err (result); | ||
499 | } | ||
500 | |||
501 | *hash = _gnutls_x509_oid2mac_algorithm (str); | ||
502 | |||
503 | if (*hash == GNUTLS_MAC_UNKNOWN) | ||
504 | { | ||
505 | |||
506 | _gnutls_x509_log ("verify.c: HASH OID: %s\n", str); | ||
507 | |||
508 | gnutls_assert (); | ||
509 | asn1_delete_structure (&dinfo); | ||
510 | return GNUTLS_E_UNKNOWN_ALGORITHM; | ||
511 | } | ||
512 | |||
513 | len = sizeof (str) - 1; | ||
514 | result = asn1_read_value (dinfo, "digestAlgorithm.parameters", str, &len); | ||
515 | /* To avoid permitting garbage in the parameters field, either the | ||
516 | parameters field is not present, or it contains 0x05 0x00. */ | ||
517 | if (! | ||
518 | (result == ASN1_ELEMENT_NOT_FOUND | ||
519 | || (result == ASN1_SUCCESS && len == 2 && str[0] == 0x05 | ||
520 | && str[1] == 0x00))) | ||
521 | { | ||
522 | gnutls_assert (); | ||
523 | asn1_delete_structure (&dinfo); | ||
524 | return GNUTLS_E_ASN1_GENERIC_ERROR; | ||
525 | } | ||
526 | |||
527 | result = asn1_read_value (dinfo, "digest", digest, digest_size); | ||
528 | if (result != ASN1_SUCCESS) | ||
529 | { | ||
530 | gnutls_assert (); | ||
531 | asn1_delete_structure (&dinfo); | ||
532 | return _gnutls_asn2err (result); | ||
533 | } | ||
534 | |||
535 | asn1_delete_structure (&dinfo); | ||
536 | |||
537 | return 0; | ||
538 | } | ||
539 | |||
540 | /* if hash==MD5 then we do RSA-MD5 | ||
541 | * if hash==SHA then we do RSA-SHA | ||
542 | * params[0] is modulus | ||
543 | * params[1] is public key | ||
544 | */ | ||
545 | static int | ||
546 | _pkcs1_rsa_verify_sig (const gnutls_datum_t * text, | ||
547 | const gnutls_datum_t * signature, | ||
548 | mpi_t * params, int params_len) | ||
549 | { | ||
550 | gnutls_mac_algorithm_t hash = GNUTLS_MAC_UNKNOWN; | ||
551 | int ret; | ||
552 | opaque digest[MAX_HASH_SIZE], md[MAX_HASH_SIZE]; | ||
553 | int digest_size; | ||
554 | GNUTLS_HASH_HANDLE hd; | ||
555 | gnutls_datum_t decrypted; | ||
556 | |||
557 | ret = | ||
558 | _gnutls_pkcs1_rsa_decrypt (&decrypted, signature, params, params_len, 1); | ||
559 | if (ret < 0) | ||
560 | { | ||
561 | gnutls_assert (); | ||
562 | return ret; | ||
563 | } | ||
564 | |||
565 | /* decrypted is a BER encoded data of type DigestInfo | ||
566 | */ | ||
567 | |||
568 | digest_size = sizeof (digest); | ||
569 | if ((ret = decode_ber_digest_info (&decrypted, &hash, digest, &digest_size)) | ||
570 | != 0) | ||
571 | { | ||
572 | gnutls_assert (); | ||
573 | _gnutls_free_datum (&decrypted); | ||
574 | return ret; | ||
575 | } | ||
576 | |||
577 | _gnutls_free_datum (&decrypted); | ||
578 | |||
579 | if (digest_size != _gnutls_hash_get_algo_len (hash)) | ||
580 | { | ||
581 | gnutls_assert (); | ||
582 | return GNUTLS_E_ASN1_GENERIC_ERROR; | ||
583 | } | ||
584 | |||
585 | hd = _gnutls_hash_init (hash); | ||
586 | if (hd == NULL) | ||
587 | { | ||
588 | gnutls_assert (); | ||
589 | return GNUTLS_E_HASH_FAILED; | ||
590 | } | ||
591 | |||
592 | _gnutls_hash (hd, text->data, text->size); | ||
593 | _gnutls_hash_deinit (hd, md); | ||
594 | |||
595 | if (memcmp (md, digest, digest_size) != 0) | ||
596 | { | ||
597 | gnutls_assert (); | ||
598 | return GNUTLS_E_PK_SIG_VERIFY_FAILED; | ||
599 | } | ||
600 | |||
601 | return 0; | ||
602 | } | ||
603 | |||
604 | /* Hashes input data and verifies a DSA signature. | ||
605 | */ | ||
606 | static int | ||
607 | dsa_verify_sig (const gnutls_datum_t * text, | ||
608 | const gnutls_datum_t * signature, | ||
609 | mpi_t * params, int params_len) | ||
610 | { | ||
611 | int ret; | ||
612 | opaque _digest[MAX_HASH_SIZE]; | ||
613 | gnutls_datum_t digest; | ||
614 | GNUTLS_HASH_HANDLE hd; | ||
615 | |||
616 | hd = _gnutls_hash_init (GNUTLS_MAC_SHA1); | ||
617 | if (hd == NULL) | ||
618 | { | ||
619 | gnutls_assert (); | ||
620 | return GNUTLS_E_HASH_FAILED; | ||
621 | } | ||
622 | |||
623 | _gnutls_hash (hd, text->data, text->size); | ||
624 | _gnutls_hash_deinit (hd, _digest); | ||
625 | |||
626 | digest.data = _digest; | ||
627 | digest.size = 20; | ||
628 | |||
629 | ret = _gnutls_dsa_verify (&digest, signature, params, params_len); | ||
630 | |||
631 | return ret; | ||
632 | } | ||
633 | |||
634 | /* Verifies the signature data, and returns 0 if not verified, | ||
635 | * or 1 otherwise. | ||
636 | */ | ||
637 | static int | ||
638 | verify_sig (const gnutls_datum_t * tbs, | ||
639 | const gnutls_datum_t * signature, | ||
640 | gnutls_pk_algorithm_t pk, | ||
641 | mpi_t * issuer_params, int issuer_params_size) | ||
642 | { | ||
643 | |||
644 | switch (pk) | ||
645 | { | ||
646 | case GNUTLS_PK_RSA: | ||
647 | |||
648 | if (_pkcs1_rsa_verify_sig | ||
649 | (tbs, signature, issuer_params, issuer_params_size) != 0) | ||
650 | { | ||
651 | gnutls_assert (); | ||
652 | return 0; | ||
653 | } | ||
654 | |||
655 | return 1; | ||
656 | break; | ||
657 | |||
658 | default: | ||
659 | gnutls_assert (); | ||
660 | return GNUTLS_E_INTERNAL_ERROR; | ||
661 | |||
662 | } | ||
663 | } | ||
664 | |||
665 | /* verifies if the certificate is properly signed. | ||
666 | * returns 0 on failure and 1 on success. | ||
667 | * | ||
668 | * 'tbs' is the signed data | ||
669 | * 'signature' is the signature! | ||
670 | */ | ||
671 | int | ||
672 | _gnutls_x509_verify_signature (const gnutls_datum_t * tbs, | ||
673 | const gnutls_datum_t * signature, | ||
674 | gnutls_x509_crt_t issuer) | ||
675 | { | ||
676 | mpi_t issuer_params[MAX_PUBLIC_PARAMS_SIZE]; | ||
677 | int ret, issuer_params_size, i; | ||
678 | |||
679 | /* Read the MPI parameters from the issuer's certificate. | ||
680 | */ | ||
681 | issuer_params_size = MAX_PUBLIC_PARAMS_SIZE; | ||
682 | ret = | ||
683 | _gnutls_x509_crt_get_mpis (issuer, issuer_params, &issuer_params_size); | ||
684 | if (ret < 0) | ||
685 | { | ||
686 | gnutls_assert (); | ||
687 | return ret; | ||
688 | } | ||
689 | |||
690 | ret = verify_sig (tbs, signature, gnutls_x509_crt_get_pk_algorithm (issuer, | ||
691 | NULL), | ||
692 | issuer_params, issuer_params_size); | ||
693 | if (ret < 0) | ||
694 | { | ||
695 | gnutls_assert (); | ||
696 | } | ||
697 | |||
698 | /* release all allocated MPIs | ||
699 | */ | ||
700 | for (i = 0; i < issuer_params_size; i++) | ||
701 | { | ||
702 | _gnutls_mpi_release (&issuer_params[i]); | ||
703 | } | ||
704 | |||
705 | return ret; | ||
706 | } | ||
707 | |||
708 | /* verifies if the certificate is properly signed. | ||
709 | * returns 0 on failure and 1 on success. | ||
710 | * | ||
711 | * 'tbs' is the signed data | ||
712 | * 'signature' is the signature! | ||
713 | */ | ||
714 | int | ||
715 | _gnutls_x509_privkey_verify_signature (const gnutls_datum_t * tbs, | ||
716 | const gnutls_datum_t * signature, | ||
717 | gnutls_x509_privkey_t issuer) | ||
718 | { | ||
719 | int ret; | ||
720 | |||
721 | ret = verify_sig (tbs, signature, issuer->pk_algorithm, issuer->params, | ||
722 | issuer->params_size); | ||
723 | if (ret < 0) | ||
724 | { | ||
725 | gnutls_assert (); | ||
726 | } | ||
727 | |||
728 | return ret; | ||
729 | } | ||
730 | |||
731 | /** | ||
732 | * gnutls_x509_crt_list_verify - This function verifies the given certificate list | ||
733 | * @cert_list: is the certificate list to be verified | ||
734 | * @cert_list_length: holds the number of certificate in cert_list | ||
735 | * @CA_list: is the CA list which will be used in verification | ||
736 | * @CA_list_length: holds the number of CA certificate in CA_list | ||
737 | * @CRL_list: holds a list of CRLs. | ||
738 | * @CRL_list_length: the length of CRL list. | ||
739 | * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations. | ||
740 | * @verify: will hold the certificate verification output. | ||
741 | * | ||
742 | * This function will try to verify the given certificate list and return its status. | ||
743 | * Note that expiration and activation dates are not checked | ||
744 | * by this function, you should check them using the appropriate functions. | ||
745 | * | ||
746 | * If no flags are specified (0), this function will use the | ||
747 | * basicConstraints (2.5.29.19) PKIX extension. This means that only a certificate | ||
748 | * authority is allowed to sign a certificate. | ||
749 | * | ||
750 | * You must also check the peer's name in order to check if the verified | ||
751 | * certificate belongs to the actual peer. | ||
752 | * | ||
753 | * The certificate verification output will be put in @verify and will be | ||
754 | * one or more of the gnutls_certificate_status_t enumerated elements bitwise or'd. | ||
755 | * For a more detailed verification status use gnutls_x509_crt_verify() per list | ||
756 | * element. | ||
757 | * | ||
758 | * GNUTLS_CERT_INVALID: the certificate chain is not valid. | ||
759 | * | ||
760 | * GNUTLS_CERT_REVOKED: a certificate in the chain has been revoked. | ||
761 | * | ||
762 | * Returns 0 on success and a negative value in case of an error. | ||
763 | * | ||
764 | **/ | ||
765 | int | ||
766 | gnutls_x509_crt_list_verify (const gnutls_x509_crt_t * cert_list, | ||
767 | int cert_list_length, | ||
768 | const gnutls_x509_crt_t * CA_list, | ||
769 | int CA_list_length, | ||
770 | const gnutls_x509_crl_t * CRL_list, | ||
771 | int CRL_list_length, | ||
772 | unsigned int flags, unsigned int *verify) | ||
773 | { | ||
774 | if (cert_list == NULL || cert_list_length == 0) | ||
775 | return GNUTLS_E_NO_CERTIFICATE_FOUND; | ||
776 | |||
777 | /* Verify certificate | ||
778 | */ | ||
779 | *verify = _gnutls_x509_verify_certificate (cert_list, cert_list_length, | ||
780 | CA_list, CA_list_length, | ||
781 | CRL_list, CRL_list_length, | ||
782 | flags); | ||
783 | |||
784 | return 0; | ||
785 | } | ||
786 | |||
787 | /** | ||
788 | * gnutls_x509_crt_verify - This function verifies the given certificate against a given trusted one | ||
789 | * @cert: is the certificate to be verified | ||
790 | * @CA_list: is one certificate that is considered to be trusted one | ||
791 | * @CA_list_length: holds the number of CA certificate in CA_list | ||
792 | * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations. | ||
793 | * @verify: will hold the certificate verification output. | ||
794 | * | ||
795 | * This function will try to verify the given certificate and return its status. | ||
796 | * The verification output in this functions cannot be GNUTLS_CERT_NOT_VALID. | ||
797 | * | ||
798 | * Returns 0 on success and a negative value in case of an error. | ||
799 | * | ||
800 | **/ | ||
801 | int | ||
802 | gnutls_x509_crt_verify (gnutls_x509_crt_t cert, | ||
803 | const gnutls_x509_crt_t * CA_list, | ||
804 | int CA_list_length, | ||
805 | unsigned int flags, unsigned int *verify) | ||
806 | { | ||
807 | int ret; | ||
808 | /* Verify certificate | ||
809 | */ | ||
810 | ret = _gnutls_verify_certificate2 (cert, CA_list, CA_list_length, flags, | ||
811 | verify); | ||
812 | if (ret < 0) | ||
813 | { | ||
814 | gnutls_assert (); | ||
815 | return ret; | ||
816 | } | ||
817 | |||
818 | return 0; | ||
819 | } | ||
820 | |||
821 | #ifdef ENABLE_PKI | ||
822 | |||
823 | /** | ||
824 | * gnutls_x509_crl_check_issuer - This function checks if the CRL given has the given issuer | ||
825 | * @crl: is the CRL to be checked | ||
826 | * @issuer: is the certificate of a possible issuer | ||
827 | * | ||
828 | * This function will check if the given CRL was issued by the | ||
829 | * given issuer certificate. It will return true (1) if the given CRL was issued | ||
830 | * by the given issuer, and false (0) if not. | ||
831 | * | ||
832 | * A negative value is returned in case of an error. | ||
833 | * | ||
834 | **/ | ||
835 | int | ||
836 | gnutls_x509_crl_check_issuer (gnutls_x509_crl_t cert, | ||
837 | gnutls_x509_crt_t issuer) | ||
838 | { | ||
839 | return is_crl_issuer (cert, issuer); | ||
840 | } | ||
841 | |||
842 | /** | ||
843 | * gnutls_x509_crl_verify - This function verifies the given crl against a given trusted one | ||
844 | * @crl: is the crl to be verified | ||
845 | * @CA_list: is a certificate list that is considered to be trusted one | ||
846 | * @CA_list_length: holds the number of CA certificates in CA_list | ||
847 | * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations. | ||
848 | * @verify: will hold the crl verification output. | ||
849 | * | ||
850 | * This function will try to verify the given crl and return its status. | ||
851 | * See gnutls_x509_crt_list_verify() for a detailed description of | ||
852 | * return values. | ||
853 | * | ||
854 | * Returns 0 on success and a negative value in case of an error. | ||
855 | * | ||
856 | **/ | ||
857 | int | ||
858 | gnutls_x509_crl_verify (gnutls_x509_crl_t crl, | ||
859 | const gnutls_x509_crt_t * CA_list, | ||
860 | int CA_list_length, unsigned int flags, | ||
861 | unsigned int *verify) | ||
862 | { | ||
863 | int ret; | ||
864 | /* Verify crl | ||
865 | */ | ||
866 | ret = _gnutls_verify_crl2 (crl, CA_list, CA_list_length, flags, verify); | ||
867 | if (ret < 0) | ||
868 | { | ||
869 | gnutls_assert (); | ||
870 | return ret; | ||
871 | } | ||
872 | |||
873 | return 0; | ||
874 | } | ||
875 | |||
876 | /* The same as above, but here we've got a CRL. | ||
877 | */ | ||
878 | static int | ||
879 | is_crl_issuer (gnutls_x509_crl_t crl, gnutls_x509_crt_t issuer_cert) | ||
880 | { | ||
881 | gnutls_datum_t dn1 = { NULL, 0 }, dn2 = | ||
882 | { | ||
883 | NULL, 0}; | ||
884 | int ret; | ||
885 | |||
886 | ret = _gnutls_x509_crl_get_raw_issuer_dn (crl, &dn1); | ||
887 | if (ret < 0) | ||
888 | { | ||
889 | gnutls_assert (); | ||
890 | goto cleanup; | ||
891 | } | ||
892 | |||
893 | ret = gnutls_x509_crt_get_raw_dn (issuer_cert, &dn2); | ||
894 | if (ret < 0) | ||
895 | { | ||
896 | gnutls_assert (); | ||
897 | return ret; | ||
898 | } | ||
899 | |||
900 | ret = _gnutls_x509_compare_raw_dn (&dn1, &dn2); | ||
901 | |||
902 | cleanup: | ||
903 | _gnutls_free_datum (&dn1); | ||
904 | _gnutls_free_datum (&dn2); | ||
905 | |||
906 | return ret; | ||
907 | } | ||
908 | |||
909 | static inline gnutls_x509_crt_t | ||
910 | find_crl_issuer (gnutls_x509_crl_t crl, | ||
911 | const gnutls_x509_crt_t * trusted_cas, int tcas_size) | ||
912 | { | ||
913 | int i; | ||
914 | |||
915 | /* this is serial search. | ||
916 | */ | ||
917 | |||
918 | for (i = 0; i < tcas_size; i++) | ||
919 | { | ||
920 | if (is_crl_issuer (crl, trusted_cas[i]) == 1) | ||
921 | return trusted_cas[i]; | ||
922 | } | ||
923 | |||
924 | gnutls_assert (); | ||
925 | return NULL; | ||
926 | } | ||
927 | |||
928 | /* | ||
929 | * Returns only 0 or 1. If 1 it means that the CRL | ||
930 | * was successfuly verified. | ||
931 | * | ||
932 | * 'flags': an OR of the gnutls_certificate_verify_flags enumeration. | ||
933 | * | ||
934 | * Output will hold information about the verification | ||
935 | * procedure. | ||
936 | */ | ||
937 | static int | ||
938 | _gnutls_verify_crl2 (gnutls_x509_crl_t crl, | ||
939 | const gnutls_x509_crt_t * trusted_cas, | ||
940 | int tcas_size, unsigned int flags, unsigned int *output) | ||
941 | { | ||
942 | /* CRL is ignored for now */ | ||
943 | gnutls_datum_t crl_signed_data = { NULL, 0 }; | ||
944 | gnutls_datum_t crl_signature = { NULL, 0 }; | ||
945 | gnutls_x509_crt_t issuer; | ||
946 | int ret, result; | ||
947 | |||
948 | if (output) | ||
949 | *output = 0; | ||
950 | |||
951 | if (tcas_size >= 1) | ||
952 | issuer = find_crl_issuer (crl, trusted_cas, tcas_size); | ||
953 | else | ||
954 | { | ||
955 | gnutls_assert (); | ||
956 | if (output) | ||
957 | *output |= GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID; | ||
958 | return 0; | ||
959 | } | ||
960 | |||
961 | /* issuer is not in trusted certificate | ||
962 | * authorities. | ||
963 | */ | ||
964 | if (issuer == NULL) | ||
965 | { | ||
966 | gnutls_assert (); | ||
967 | if (output) | ||
968 | *output |= GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID; | ||
969 | return 0; | ||
970 | } | ||
971 | |||
972 | if (!(flags & GNUTLS_VERIFY_DISABLE_CA_SIGN)) | ||
973 | { | ||
974 | if (gnutls_x509_crt_get_ca_status (issuer, NULL) != 1) | ||
975 | { | ||
976 | gnutls_assert (); | ||
977 | if (output) | ||
978 | *output |= GNUTLS_CERT_SIGNER_NOT_CA | GNUTLS_CERT_INVALID; | ||
979 | return 0; | ||
980 | } | ||
981 | } | ||
982 | |||
983 | result = | ||
984 | _gnutls_x509_get_signed_data (crl->crl, "tbsCertList", &crl_signed_data); | ||
985 | if (result < 0) | ||
986 | { | ||
987 | gnutls_assert (); | ||
988 | goto cleanup; | ||
989 | } | ||
990 | |||
991 | result = _gnutls_x509_get_signature (crl->crl, "signature", &crl_signature); | ||
992 | if (result < 0) | ||
993 | { | ||
994 | gnutls_assert (); | ||
995 | goto cleanup; | ||
996 | } | ||
997 | |||
998 | ret = | ||
999 | _gnutls_x509_verify_signature (&crl_signed_data, &crl_signature, issuer); | ||
1000 | if (ret < 0) | ||
1001 | { | ||
1002 | gnutls_assert (); | ||
1003 | } | ||
1004 | else if (ret == 0) | ||
1005 | { | ||
1006 | gnutls_assert (); | ||
1007 | /* error. ignore it */ | ||
1008 | if (output) | ||
1009 | *output |= GNUTLS_CERT_INVALID; | ||
1010 | ret = 0; | ||
1011 | } | ||
1012 | |||
1013 | { | ||
1014 | int sigalg; | ||
1015 | |||
1016 | sigalg = gnutls_x509_crl_get_signature_algorithm (crl); | ||
1017 | |||
1018 | if (((sigalg == GNUTLS_SIGN_RSA_MD2) && | ||
1019 | !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2)) || | ||
1020 | ((sigalg == GNUTLS_SIGN_RSA_MD5) && | ||
1021 | !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5))) | ||
1022 | { | ||
1023 | if (output) | ||
1024 | *output |= GNUTLS_CERT_INSECURE_ALGORITHM | GNUTLS_CERT_INVALID; | ||
1025 | } | ||
1026 | } | ||
1027 | |||
1028 | result = ret; | ||
1029 | |||
1030 | cleanup: | ||
1031 | _gnutls_free_datum (&crl_signed_data); | ||
1032 | _gnutls_free_datum (&crl_signature); | ||
1033 | |||
1034 | return result; | ||
1035 | } | ||
1036 | |||
1037 | #endif | ||
diff --git a/src/daemon/https/x509/x509_write.c b/src/daemon/https/x509/x509_write.c new file mode 100644 index 00000000..d9529c33 --- /dev/null +++ b/src/daemon/https/x509/x509_write.c | |||
@@ -0,0 +1,1094 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation | ||
3 | * | ||
4 | * Author: Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GNUTLS. | ||
7 | * | ||
8 | * The GNUTLS library 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 | ||
19 | * License along with this library; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, | ||
21 | * USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | /* This file contains functions to handle X.509 certificate generation. | ||
26 | */ | ||
27 | |||
28 | #include <gnutls_int.h> | ||
29 | |||
30 | #ifdef ENABLE_PKI | ||
31 | |||
32 | #include <gnutls_datum.h> | ||
33 | #include <gnutls_global.h> | ||
34 | #include <gnutls_errors.h> | ||
35 | #include <common.h> | ||
36 | #include <gnutls_x509.h> | ||
37 | #include <x509_b64.h> | ||
38 | #include <crq.h> | ||
39 | #include <dn.h> | ||
40 | #include <mpi.h> | ||
41 | #include <sign.h> | ||
42 | #include <extensions.h> | ||
43 | #include <libtasn1.h> | ||
44 | |||
45 | static void disable_optional_stuff (gnutls_x509_crt_t cert); | ||
46 | |||
47 | /** | ||
48 | * gnutls_x509_crt_set_dn_by_oid - This function will set the Certificate request subject's distinguished name | ||
49 | * @crt: should contain a gnutls_x509_crt_t structure | ||
50 | * @oid: holds an Object Identifier in a null terminated string | ||
51 | * @raw_flag: must be 0, or 1 if the data are DER encoded | ||
52 | * @name: a pointer to the name | ||
53 | * @sizeof_name: holds the size of @name | ||
54 | * | ||
55 | * This function will set the part of the name of the Certificate subject, specified | ||
56 | * by the given OID. The input string should be ASCII or UTF-8 encoded. | ||
57 | * | ||
58 | * Some helper macros with popular OIDs can be found in gnutls/x509.h | ||
59 | * With this function you can only set the known OIDs. You can test | ||
60 | * for known OIDs using gnutls_x509_dn_oid_known(). For OIDs that are | ||
61 | * not known (by gnutls) you should properly DER encode your data, and | ||
62 | * call this function with raw_flag set. | ||
63 | * | ||
64 | * Returns 0 on success. | ||
65 | * | ||
66 | **/ | ||
67 | int | ||
68 | gnutls_x509_crt_set_dn_by_oid (gnutls_x509_crt_t crt, const char *oid, | ||
69 | unsigned int raw_flag, const void *name, | ||
70 | unsigned int sizeof_name) | ||
71 | { | ||
72 | if (sizeof_name == 0 || name == NULL || crt == NULL) | ||
73 | { | ||
74 | return GNUTLS_E_INVALID_REQUEST; | ||
75 | } | ||
76 | |||
77 | return _gnutls_x509_set_dn_oid (crt->cert, "tbsCertificate.subject", | ||
78 | oid, raw_flag, name, sizeof_name); | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | * gnutls_x509_crt_set_issuer_dn_by_oid - This function will set the Certificate request issuer's distinguished name | ||
83 | * @crt: should contain a gnutls_x509_crt_t structure | ||
84 | * @oid: holds an Object Identifier in a null terminated string | ||
85 | * @raw_flag: must be 0, or 1 if the data are DER encoded | ||
86 | * @name: a pointer to the name | ||
87 | * @sizeof_name: holds the size of @name | ||
88 | * | ||
89 | * This function will set the part of the name of the Certificate issuer, specified | ||
90 | * by the given OID. The input string should be ASCII or UTF-8 encoded. | ||
91 | * | ||
92 | * Some helper macros with popular OIDs can be found in gnutls/x509.h | ||
93 | * With this function you can only set the known OIDs. You can test | ||
94 | * for known OIDs using gnutls_x509_dn_oid_known(). For OIDs that are | ||
95 | * not known (by gnutls) you should properly DER encode your data, and | ||
96 | * call this function with raw_flag set. | ||
97 | * | ||
98 | * Normally you do not need to call this function, since the signing | ||
99 | * operation will copy the signer's name as the issuer of the certificate. | ||
100 | * | ||
101 | * Returns 0 on success. | ||
102 | * | ||
103 | **/ | ||
104 | int | ||
105 | gnutls_x509_crt_set_issuer_dn_by_oid (gnutls_x509_crt_t crt, | ||
106 | const char *oid, | ||
107 | unsigned int raw_flag, | ||
108 | const void *name, | ||
109 | unsigned int sizeof_name) | ||
110 | { | ||
111 | if (sizeof_name == 0 || name == NULL || crt == NULL) | ||
112 | { | ||
113 | return GNUTLS_E_INVALID_REQUEST; | ||
114 | } | ||
115 | |||
116 | return _gnutls_x509_set_dn_oid (crt->cert, "tbsCertificate.issuer", oid, | ||
117 | raw_flag, name, sizeof_name); | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * gnutls_x509_crt_set_proxy_dn - Set Proxy Certificate subject's distinguished name | ||
122 | * @crt: a gnutls_x509_crt_t structure with the new proxy cert | ||
123 | * @eecrt: the end entity certificate that will be issuing the proxy | ||
124 | * @raw_flag: must be 0, or 1 if the CN is DER encoded | ||
125 | * @name: a pointer to the CN name, may be NULL (but MUST then be added later) | ||
126 | * @sizeof_name: holds the size of @name | ||
127 | * | ||
128 | * This function will set the subject in @crt to the end entity's | ||
129 | * @eecrt subject name, and add a single Common Name component @name | ||
130 | * of size @sizeof_name. This corresponds to the required proxy | ||
131 | * certificate naming style. Note that if @name is %NULL, you MUST | ||
132 | * set it later by using gnutls_x509_crt_set_dn_by_oid() or similar. | ||
133 | * | ||
134 | * Returns 0 on success. | ||
135 | * | ||
136 | **/ | ||
137 | int | ||
138 | gnutls_x509_crt_set_proxy_dn (gnutls_x509_crt_t crt, gnutls_x509_crt_t eecrt, | ||
139 | unsigned int raw_flag, const void *name, | ||
140 | unsigned int sizeof_name) | ||
141 | { | ||
142 | int result; | ||
143 | |||
144 | if (crt == NULL || eecrt == NULL) | ||
145 | { | ||
146 | return GNUTLS_E_INVALID_REQUEST; | ||
147 | } | ||
148 | |||
149 | result = asn1_copy_node (crt->cert, "tbsCertificate.subject", | ||
150 | eecrt->cert, "tbsCertificate.subject"); | ||
151 | if (result != ASN1_SUCCESS) | ||
152 | { | ||
153 | gnutls_assert (); | ||
154 | return _gnutls_asn2err (result); | ||
155 | } | ||
156 | |||
157 | if (name && sizeof_name) | ||
158 | { | ||
159 | return _gnutls_x509_set_dn_oid (crt->cert, "tbsCertificate.subject", | ||
160 | GNUTLS_OID_X520_COMMON_NAME, | ||
161 | raw_flag, name, sizeof_name); | ||
162 | } | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | /** | ||
168 | * gnutls_x509_crt_set_version - This function will set the Certificate request version | ||
169 | * @crt: should contain a gnutls_x509_crt_t structure | ||
170 | * @version: holds the version number. For X.509v1 certificates must be 1. | ||
171 | * | ||
172 | * This function will set the version of the certificate. This must | ||
173 | * be one for X.509 version 1, and so on. Plain certificates without | ||
174 | * extensions must have version set to one. | ||
175 | * | ||
176 | * To create well-formed certificates, you must specify version 3 if | ||
177 | * you use any certificate extensions. Extensions are created by | ||
178 | * functions such as gnutls_x509_crt_set_subject_alternative_name or | ||
179 | * gnutls_x509_crt_set_key_usage. | ||
180 | * | ||
181 | * Returns 0 on success. | ||
182 | * | ||
183 | **/ | ||
184 | int | ||
185 | gnutls_x509_crt_set_version (gnutls_x509_crt_t crt, unsigned int version) | ||
186 | { | ||
187 | int result; | ||
188 | unsigned char null = version; | ||
189 | |||
190 | if (crt == NULL) | ||
191 | { | ||
192 | gnutls_assert (); | ||
193 | return GNUTLS_E_INVALID_REQUEST; | ||
194 | } | ||
195 | |||
196 | if (null > 0) | ||
197 | null--; | ||
198 | |||
199 | result = asn1_write_value (crt->cert, "tbsCertificate.version", &null, 1); | ||
200 | if (result != ASN1_SUCCESS) | ||
201 | { | ||
202 | gnutls_assert (); | ||
203 | return _gnutls_asn2err (result); | ||
204 | } | ||
205 | |||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | /** | ||
210 | * gnutls_x509_crt_set_key - This function will associate the Certificate with a key | ||
211 | * @crt: should contain a gnutls_x509_crt_t structure | ||
212 | * @key: holds a private key | ||
213 | * | ||
214 | * This function will set the public parameters from the given private key to the | ||
215 | * certificate. Only RSA keys are currently supported. | ||
216 | * | ||
217 | * Returns 0 on success. | ||
218 | * | ||
219 | **/ | ||
220 | int | ||
221 | gnutls_x509_crt_set_key (gnutls_x509_crt_t crt, gnutls_x509_privkey_t key) | ||
222 | { | ||
223 | int result; | ||
224 | |||
225 | if (crt == NULL) | ||
226 | { | ||
227 | gnutls_assert (); | ||
228 | return GNUTLS_E_INVALID_REQUEST; | ||
229 | } | ||
230 | |||
231 | result = _gnutls_x509_encode_and_copy_PKI_params (crt->cert, | ||
232 | "tbsCertificate.subjectPublicKeyInfo", | ||
233 | key->pk_algorithm, | ||
234 | key->params, | ||
235 | key->params_size); | ||
236 | |||
237 | if (result < 0) | ||
238 | { | ||
239 | gnutls_assert (); | ||
240 | return result; | ||
241 | } | ||
242 | |||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | /** | ||
247 | * gnutls_x509_crt_set_crq - This function will associate the Certificate with a request | ||
248 | * @crt: should contain a gnutls_x509_crt_t structure | ||
249 | * @crq: holds a certificate request | ||
250 | * | ||
251 | * This function will set the name and public parameters from the given certificate request to the | ||
252 | * certificate. Only RSA keys are currently supported. | ||
253 | * | ||
254 | * Returns 0 on success. | ||
255 | * | ||
256 | **/ | ||
257 | int | ||
258 | gnutls_x509_crt_set_crq (gnutls_x509_crt_t crt, gnutls_x509_crq_t crq) | ||
259 | { | ||
260 | int result; | ||
261 | int pk_algorithm; | ||
262 | |||
263 | if (crt == NULL || crq == NULL) | ||
264 | { | ||
265 | gnutls_assert (); | ||
266 | return GNUTLS_E_INVALID_REQUEST; | ||
267 | } | ||
268 | |||
269 | pk_algorithm = gnutls_x509_crq_get_pk_algorithm (crq, NULL); | ||
270 | |||
271 | result = asn1_copy_node (crt->cert, "tbsCertificate.subject", | ||
272 | crq->crq, "certificationRequestInfo.subject"); | ||
273 | if (result != ASN1_SUCCESS) | ||
274 | { | ||
275 | gnutls_assert (); | ||
276 | return _gnutls_asn2err (result); | ||
277 | } | ||
278 | |||
279 | result = | ||
280 | asn1_copy_node (crt->cert, "tbsCertificate.subjectPublicKeyInfo", | ||
281 | crq->crq, "certificationRequestInfo.subjectPKInfo"); | ||
282 | if (result != ASN1_SUCCESS) | ||
283 | { | ||
284 | gnutls_assert (); | ||
285 | return _gnutls_asn2err (result); | ||
286 | } | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | /** | ||
292 | * gnutls_x509_crt_set_extension_by_oid - This function will set an arbitrary extension | ||
293 | * @crt: should contain a gnutls_x509_crt_t structure | ||
294 | * @oid: holds an Object Identified in null terminated string | ||
295 | * @buf: a pointer to a DER encoded data | ||
296 | * @sizeof_buf: holds the size of @buf | ||
297 | * @critical: should be non zero if the extension is to be marked as critical | ||
298 | * | ||
299 | * This function will set an the extension, by the specified OID, in the certificate. | ||
300 | * The extension data should be binary data DER encoded. | ||
301 | * | ||
302 | * Returns 0 on success and a negative value in case of an error. | ||
303 | * | ||
304 | **/ | ||
305 | int | ||
306 | gnutls_x509_crt_set_extension_by_oid (gnutls_x509_crt_t crt, | ||
307 | const char *oid, const void *buf, | ||
308 | size_t sizeof_buf, | ||
309 | unsigned int critical) | ||
310 | { | ||
311 | int result; | ||
312 | gnutls_datum_t der_data; | ||
313 | |||
314 | der_data.data = (void *) buf; | ||
315 | der_data.size = sizeof_buf; | ||
316 | |||
317 | if (crt == NULL) | ||
318 | { | ||
319 | gnutls_assert (); | ||
320 | return GNUTLS_E_INVALID_REQUEST; | ||
321 | } | ||
322 | |||
323 | result = _gnutls_x509_crt_set_extension (crt, oid, &der_data, critical); | ||
324 | if (result < 0) | ||
325 | { | ||
326 | gnutls_assert (); | ||
327 | return result; | ||
328 | } | ||
329 | |||
330 | crt->use_extensions = 1; | ||
331 | |||
332 | return 0; | ||
333 | |||
334 | } | ||
335 | |||
336 | /** | ||
337 | * gnutls_x509_crt_set_basic_constraints - This function will set the basicConstraints extension | ||
338 | * @crt: should contain a gnutls_x509_crt_t structure | ||
339 | * @ca: true(1) or false(0). Depending on the Certificate authority status. | ||
340 | * @pathLenConstraint: non-negative values indicate maximum length of path, | ||
341 | * and negative values indicate that the pathLenConstraints field should | ||
342 | * not be present. | ||
343 | * | ||
344 | * This function will set the basicConstraints certificate extension. | ||
345 | * | ||
346 | * Returns 0 on success. | ||
347 | * | ||
348 | **/ | ||
349 | int | ||
350 | gnutls_x509_crt_set_basic_constraints (gnutls_x509_crt_t crt, | ||
351 | unsigned int ca, int pathLenConstraint) | ||
352 | { | ||
353 | int result; | ||
354 | gnutls_datum_t der_data; | ||
355 | |||
356 | if (crt == NULL) | ||
357 | { | ||
358 | gnutls_assert (); | ||
359 | return GNUTLS_E_INVALID_REQUEST; | ||
360 | } | ||
361 | |||
362 | /* generate the extension. | ||
363 | */ | ||
364 | result = _gnutls_x509_ext_gen_basicConstraints (ca, pathLenConstraint, | ||
365 | &der_data); | ||
366 | if (result < 0) | ||
367 | { | ||
368 | gnutls_assert (); | ||
369 | return result; | ||
370 | } | ||
371 | |||
372 | result = _gnutls_x509_crt_set_extension (crt, "2.5.29.19", &der_data, 1); | ||
373 | |||
374 | _gnutls_free_datum (&der_data); | ||
375 | |||
376 | if (result < 0) | ||
377 | { | ||
378 | gnutls_assert (); | ||
379 | return result; | ||
380 | } | ||
381 | |||
382 | crt->use_extensions = 1; | ||
383 | |||
384 | return 0; | ||
385 | } | ||
386 | |||
387 | /** | ||
388 | * gnutls_x509_crt_set_ca_status - This function will set the basicConstraints extension | ||
389 | * @crt: should contain a gnutls_x509_crt_t structure | ||
390 | * @ca: true(1) or false(0). Depending on the Certificate authority status. | ||
391 | * | ||
392 | * This function will set the basicConstraints certificate extension. | ||
393 | * Use gnutls_x509_crt_set_basic_constraints() if you want to control | ||
394 | * the pathLenConstraint field too. | ||
395 | * | ||
396 | * Returns 0 on success. | ||
397 | * | ||
398 | **/ | ||
399 | int | ||
400 | gnutls_x509_crt_set_ca_status (gnutls_x509_crt_t crt, unsigned int ca) | ||
401 | { | ||
402 | return gnutls_x509_crt_set_basic_constraints (crt, ca, -1); | ||
403 | } | ||
404 | |||
405 | /** | ||
406 | * gnutls_x509_crt_set_key_usage - This function will set the keyUsage extension | ||
407 | * @crt: should contain a gnutls_x509_crt_t structure | ||
408 | * @usage: an ORed sequence of the GNUTLS_KEY_* elements. | ||
409 | * | ||
410 | * This function will set the keyUsage certificate extension. | ||
411 | * | ||
412 | * Returns 0 on success. | ||
413 | * | ||
414 | **/ | ||
415 | int | ||
416 | gnutls_x509_crt_set_key_usage (gnutls_x509_crt_t crt, unsigned int usage) | ||
417 | { | ||
418 | int result; | ||
419 | gnutls_datum_t der_data; | ||
420 | |||
421 | if (crt == NULL) | ||
422 | { | ||
423 | gnutls_assert (); | ||
424 | return GNUTLS_E_INVALID_REQUEST; | ||
425 | } | ||
426 | |||
427 | /* generate the extension. | ||
428 | */ | ||
429 | result = _gnutls_x509_ext_gen_keyUsage ((uint16_t) usage, &der_data); | ||
430 | if (result < 0) | ||
431 | { | ||
432 | gnutls_assert (); | ||
433 | return result; | ||
434 | } | ||
435 | |||
436 | result = _gnutls_x509_crt_set_extension (crt, "2.5.29.15", &der_data, 1); | ||
437 | |||
438 | _gnutls_free_datum (&der_data); | ||
439 | |||
440 | if (result < 0) | ||
441 | { | ||
442 | gnutls_assert (); | ||
443 | return result; | ||
444 | } | ||
445 | |||
446 | crt->use_extensions = 1; | ||
447 | |||
448 | return 0; | ||
449 | } | ||
450 | |||
451 | /** | ||
452 | * gnutls_x509_crt_set_subject_alternative_name - This function will set the subject Alternative Name | ||
453 | * @crt: should contain a gnutls_x509_crt_t structure | ||
454 | * @type: is one of the gnutls_x509_subject_alt_name_t enumerations | ||
455 | * @data_string: The data to be set | ||
456 | * | ||
457 | * This function will set the subject alternative name certificate extension. | ||
458 | * | ||
459 | * Returns 0 on success. | ||
460 | * | ||
461 | **/ | ||
462 | int | ||
463 | gnutls_x509_crt_set_subject_alternative_name (gnutls_x509_crt_t crt, | ||
464 | gnutls_x509_subject_alt_name_t | ||
465 | type, const char *data_string) | ||
466 | { | ||
467 | int result; | ||
468 | gnutls_datum_t der_data; | ||
469 | gnutls_datum_t dnsname; | ||
470 | unsigned int critical; | ||
471 | |||
472 | if (crt == NULL) | ||
473 | { | ||
474 | gnutls_assert (); | ||
475 | return GNUTLS_E_INVALID_REQUEST; | ||
476 | } | ||
477 | |||
478 | /* Check if the extension already exists. | ||
479 | */ | ||
480 | result = | ||
481 | _gnutls_x509_crt_get_extension (crt, "2.5.29.17", 0, &dnsname, &critical); | ||
482 | |||
483 | if (result >= 0) | ||
484 | _gnutls_free_datum (&dnsname); | ||
485 | if (result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) | ||
486 | { | ||
487 | gnutls_assert (); | ||
488 | return GNUTLS_E_INVALID_REQUEST; | ||
489 | } | ||
490 | |||
491 | /* generate the extension. | ||
492 | */ | ||
493 | result = | ||
494 | _gnutls_x509_ext_gen_subject_alt_name (type, data_string, &der_data); | ||
495 | if (result < 0) | ||
496 | { | ||
497 | gnutls_assert (); | ||
498 | return result; | ||
499 | } | ||
500 | |||
501 | result = _gnutls_x509_crt_set_extension (crt, "2.5.29.17", &der_data, 0); | ||
502 | |||
503 | _gnutls_free_datum (&der_data); | ||
504 | |||
505 | if (result < 0) | ||
506 | { | ||
507 | gnutls_assert (); | ||
508 | return result; | ||
509 | } | ||
510 | |||
511 | crt->use_extensions = 1; | ||
512 | |||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | /** | ||
517 | * gnutls_x509_crt_set_proxy - Set the proxyCertInfo extension | ||
518 | * @crt: should contain a gnutls_x509_crt_t structure | ||
519 | * @pathLenConstraint: non-negative values indicate maximum length of path, | ||
520 | * and negative values indicate that the pathLenConstraints field should | ||
521 | * not be present. | ||
522 | * @policyLanguage: OID describing the language of @policy. | ||
523 | * @policy: opaque byte array with policy language, can be %NULL | ||
524 | * @sizeof_policy: size of @policy. | ||
525 | * | ||
526 | * This function will set the proxyCertInfo extension. | ||
527 | * | ||
528 | * Returns 0 on success. | ||
529 | * | ||
530 | **/ | ||
531 | int | ||
532 | gnutls_x509_crt_set_proxy (gnutls_x509_crt_t crt, | ||
533 | int pathLenConstraint, | ||
534 | const char *policyLanguage, | ||
535 | const char *policy, size_t sizeof_policy) | ||
536 | { | ||
537 | int result; | ||
538 | gnutls_datum_t der_data; | ||
539 | |||
540 | if (crt == NULL) | ||
541 | { | ||
542 | gnutls_assert (); | ||
543 | return GNUTLS_E_INVALID_REQUEST; | ||
544 | } | ||
545 | |||
546 | /* generate the extension. | ||
547 | */ | ||
548 | result = _gnutls_x509_ext_gen_proxyCertInfo (pathLenConstraint, | ||
549 | policyLanguage, | ||
550 | policy, sizeof_policy, | ||
551 | &der_data); | ||
552 | if (result < 0) | ||
553 | { | ||
554 | gnutls_assert (); | ||
555 | return result; | ||
556 | } | ||
557 | |||
558 | result = _gnutls_x509_crt_set_extension (crt, "1.3.6.1.5.5.7.1.14", | ||
559 | &der_data, 1); | ||
560 | |||
561 | _gnutls_free_datum (&der_data); | ||
562 | |||
563 | if (result < 0) | ||
564 | { | ||
565 | gnutls_assert (); | ||
566 | return result; | ||
567 | } | ||
568 | |||
569 | crt->use_extensions = 1; | ||
570 | |||
571 | return 0; | ||
572 | } | ||
573 | |||
574 | /** | ||
575 | * gnutls_x509_crt_sign2 - This function will sign a certificate with a key | ||
576 | * @crt: should contain a gnutls_x509_crt_t structure | ||
577 | * @issuer: is the certificate of the certificate issuer | ||
578 | * @issuer_key: holds the issuer's private key | ||
579 | * @dig: The message digest to use. GNUTLS_DIG_SHA1 is the safe choice unless you know what you're doing. | ||
580 | * @flags: must be 0 | ||
581 | * | ||
582 | * This function will sign the certificate with the issuer's private key, and | ||
583 | * will copy the issuer's information into the certificate. | ||
584 | * | ||
585 | * This must be the last step in a certificate generation since all | ||
586 | * the previously set parameters are now signed. | ||
587 | * | ||
588 | * Returns 0 on success. | ||
589 | * | ||
590 | **/ | ||
591 | int | ||
592 | gnutls_x509_crt_sign2 (gnutls_x509_crt_t crt, gnutls_x509_crt_t issuer, | ||
593 | gnutls_x509_privkey_t issuer_key, | ||
594 | gnutls_digest_algorithm_t dig, unsigned int flags) | ||
595 | { | ||
596 | int result; | ||
597 | |||
598 | if (crt == NULL || issuer == NULL || issuer_key == NULL) | ||
599 | { | ||
600 | gnutls_assert (); | ||
601 | return GNUTLS_E_INVALID_REQUEST; | ||
602 | } | ||
603 | |||
604 | /* disable all the unneeded OPTIONAL fields. | ||
605 | */ | ||
606 | disable_optional_stuff (crt); | ||
607 | |||
608 | result = _gnutls_x509_pkix_sign (crt->cert, "tbsCertificate", | ||
609 | dig, issuer, issuer_key); | ||
610 | if (result < 0) | ||
611 | { | ||
612 | gnutls_assert (); | ||
613 | return result; | ||
614 | } | ||
615 | |||
616 | return 0; | ||
617 | } | ||
618 | |||
619 | /** | ||
620 | * gnutls_x509_crt_sign - This function will sign a certificate with a key | ||
621 | * @crt: should contain a gnutls_x509_crt_t structure | ||
622 | * @issuer: is the certificate of the certificate issuer | ||
623 | * @issuer_key: holds the issuer's private key | ||
624 | * | ||
625 | * This function is the same a gnutls_x509_crt_sign2() with no flags, and | ||
626 | * SHA1 as the hash algorithm. | ||
627 | * | ||
628 | * Returns 0 on success. | ||
629 | * | ||
630 | **/ | ||
631 | int | ||
632 | gnutls_x509_crt_sign (gnutls_x509_crt_t crt, gnutls_x509_crt_t issuer, | ||
633 | gnutls_x509_privkey_t issuer_key) | ||
634 | { | ||
635 | return gnutls_x509_crt_sign2 (crt, issuer, issuer_key, GNUTLS_DIG_SHA1, 0); | ||
636 | } | ||
637 | |||
638 | /** | ||
639 | * gnutls_x509_crt_set_activation_time - This function will set the Certificate's activation time | ||
640 | * @cert: should contain a gnutls_x509_crt_t structure | ||
641 | * @act_time: The actual time | ||
642 | * | ||
643 | * This function will set the time this Certificate was or will be activated. | ||
644 | * | ||
645 | * Returns 0 on success, or a negative value in case of an error. | ||
646 | * | ||
647 | **/ | ||
648 | int | ||
649 | gnutls_x509_crt_set_activation_time (gnutls_x509_crt_t cert, time_t act_time) | ||
650 | { | ||
651 | if (cert == NULL) | ||
652 | { | ||
653 | gnutls_assert (); | ||
654 | return GNUTLS_E_INVALID_REQUEST; | ||
655 | } | ||
656 | |||
657 | return _gnutls_x509_set_time (cert->cert, | ||
658 | "tbsCertificate.validity.notBefore", | ||
659 | act_time); | ||
660 | } | ||
661 | |||
662 | /** | ||
663 | * gnutls_x509_crt_set_expiration_time - This function will set the Certificate's expiration time | ||
664 | * @cert: should contain a gnutls_x509_crt_t structure | ||
665 | * @exp_time: The actual time | ||
666 | * | ||
667 | * This function will set the time this Certificate will expire. | ||
668 | * | ||
669 | * Returns 0 on success, or a negative value in case of an error. | ||
670 | * | ||
671 | **/ | ||
672 | int | ||
673 | gnutls_x509_crt_set_expiration_time (gnutls_x509_crt_t cert, time_t exp_time) | ||
674 | { | ||
675 | if (cert == NULL) | ||
676 | { | ||
677 | gnutls_assert (); | ||
678 | return GNUTLS_E_INVALID_REQUEST; | ||
679 | } | ||
680 | return _gnutls_x509_set_time (cert->cert, | ||
681 | "tbsCertificate.validity.notAfter", exp_time); | ||
682 | } | ||
683 | |||
684 | /** | ||
685 | * gnutls_x509_crt_set_serial - This function will set the certificate's serial number | ||
686 | * @cert: should contain a gnutls_x509_crt_t structure | ||
687 | * @serial: The serial number | ||
688 | * @serial_size: Holds the size of the serial field. | ||
689 | * | ||
690 | * This function will set the X.509 certificate's serial number. | ||
691 | * Serial is not always a 32 or 64bit number. Some CAs use | ||
692 | * large serial numbers, thus it may be wise to handle it as something | ||
693 | * opaque. | ||
694 | * | ||
695 | * Returns 0 on success, or a negative value in case of an error. | ||
696 | * | ||
697 | **/ | ||
698 | int | ||
699 | gnutls_x509_crt_set_serial (gnutls_x509_crt_t cert, const void *serial, | ||
700 | size_t serial_size) | ||
701 | { | ||
702 | int ret; | ||
703 | |||
704 | if (cert == NULL) | ||
705 | { | ||
706 | gnutls_assert (); | ||
707 | return GNUTLS_E_INVALID_REQUEST; | ||
708 | } | ||
709 | |||
710 | ret = | ||
711 | asn1_write_value (cert->cert, "tbsCertificate.serialNumber", serial, | ||
712 | serial_size); | ||
713 | if (ret != ASN1_SUCCESS) | ||
714 | { | ||
715 | gnutls_assert (); | ||
716 | return _gnutls_asn2err (ret); | ||
717 | } | ||
718 | |||
719 | return 0; | ||
720 | |||
721 | } | ||
722 | |||
723 | /* If OPTIONAL fields have not been initialized then | ||
724 | * disable them. | ||
725 | */ | ||
726 | static void | ||
727 | disable_optional_stuff (gnutls_x509_crt_t cert) | ||
728 | { | ||
729 | |||
730 | asn1_write_value (cert->cert, "tbsCertificate.issuerUniqueID", NULL, 0); | ||
731 | |||
732 | asn1_write_value (cert->cert, "tbsCertificate.subjectUniqueID", NULL, 0); | ||
733 | |||
734 | if (cert->use_extensions == 0) | ||
735 | { | ||
736 | _gnutls_x509_log ("Disabling X.509 extensions.\n"); | ||
737 | asn1_write_value (cert->cert, "tbsCertificate.extensions", NULL, 0); | ||
738 | } | ||
739 | |||
740 | return; | ||
741 | } | ||
742 | |||
743 | /** | ||
744 | * gnutls_x509_crt_set_crl_dist_points - This function will set the CRL dist points | ||
745 | * @crt: should contain a gnutls_x509_crt_t structure | ||
746 | * @type: is one of the gnutls_x509_subject_alt_name_t enumerations | ||
747 | * @data_string: The data to be set | ||
748 | * @reason_flags: revocation reasons | ||
749 | * | ||
750 | * This function will set the CRL distribution points certificate extension. | ||
751 | * | ||
752 | * Returns 0 on success. | ||
753 | * | ||
754 | **/ | ||
755 | int | ||
756 | gnutls_x509_crt_set_crl_dist_points (gnutls_x509_crt_t crt, | ||
757 | gnutls_x509_subject_alt_name_t | ||
758 | type, const void *data_string, | ||
759 | unsigned int reason_flags) | ||
760 | { | ||
761 | int result; | ||
762 | gnutls_datum_t der_data; | ||
763 | gnutls_datum_t oldname; | ||
764 | unsigned int critical; | ||
765 | |||
766 | if (crt == NULL) | ||
767 | { | ||
768 | gnutls_assert (); | ||
769 | return GNUTLS_E_INVALID_REQUEST; | ||
770 | } | ||
771 | |||
772 | /* Check if the extension already exists. | ||
773 | */ | ||
774 | result = | ||
775 | _gnutls_x509_crt_get_extension (crt, "2.5.29.31", 0, &oldname, &critical); | ||
776 | |||
777 | if (result >= 0) | ||
778 | _gnutls_free_datum (&oldname); | ||
779 | if (result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) | ||
780 | { | ||
781 | gnutls_assert (); | ||
782 | return GNUTLS_E_INVALID_REQUEST; | ||
783 | } | ||
784 | |||
785 | /* generate the extension. | ||
786 | */ | ||
787 | result = | ||
788 | _gnutls_x509_ext_gen_crl_dist_points (type, data_string, | ||
789 | reason_flags, &der_data); | ||
790 | if (result < 0) | ||
791 | { | ||
792 | gnutls_assert (); | ||
793 | return result; | ||
794 | } | ||
795 | |||
796 | result = _gnutls_x509_crt_set_extension (crt, "2.5.29.31", &der_data, 0); | ||
797 | |||
798 | _gnutls_free_datum (&der_data); | ||
799 | |||
800 | if (result < 0) | ||
801 | { | ||
802 | gnutls_assert (); | ||
803 | return result; | ||
804 | } | ||
805 | |||
806 | crt->use_extensions = 1; | ||
807 | |||
808 | return 0; | ||
809 | } | ||
810 | |||
811 | /** | ||
812 | * gnutls_x509_crt_cpy_crl_dist_points - This function will copy the CRL dist points | ||
813 | * @dst: should contain a gnutls_x509_crt_t structure | ||
814 | * @src: the certificate where the dist points will be copied from | ||
815 | * | ||
816 | * This function will copy the CRL distribution points certificate | ||
817 | * extension, from the source to the destination certificate. | ||
818 | * This may be useful to copy from a CA certificate to issued ones. | ||
819 | * | ||
820 | * Returns 0 on success. | ||
821 | * | ||
822 | **/ | ||
823 | int | ||
824 | gnutls_x509_crt_cpy_crl_dist_points (gnutls_x509_crt_t dst, | ||
825 | gnutls_x509_crt_t src) | ||
826 | { | ||
827 | int result; | ||
828 | gnutls_datum_t der_data; | ||
829 | unsigned int critical; | ||
830 | |||
831 | if (dst == NULL || src == NULL) | ||
832 | { | ||
833 | gnutls_assert (); | ||
834 | return GNUTLS_E_INVALID_REQUEST; | ||
835 | } | ||
836 | |||
837 | /* Check if the extension already exists. | ||
838 | */ | ||
839 | result = | ||
840 | _gnutls_x509_crt_get_extension (src, "2.5.29.31", 0, &der_data, | ||
841 | &critical); | ||
842 | if (result < 0) | ||
843 | { | ||
844 | gnutls_assert (); | ||
845 | return result; | ||
846 | } | ||
847 | |||
848 | result = | ||
849 | _gnutls_x509_crt_set_extension (dst, "2.5.29.31", &der_data, critical); | ||
850 | _gnutls_free_datum (&der_data); | ||
851 | |||
852 | if (result < 0) | ||
853 | { | ||
854 | gnutls_assert (); | ||
855 | return result; | ||
856 | } | ||
857 | |||
858 | dst->use_extensions = 1; | ||
859 | |||
860 | return 0; | ||
861 | } | ||
862 | |||
863 | /** | ||
864 | * gnutls_x509_crt_set_subject_key_id - This function will set the certificate's subject key id | ||
865 | * @cert: should contain a gnutls_x509_crt_t structure | ||
866 | * @id: The key ID | ||
867 | * @id_size: Holds the size of the serial field. | ||
868 | * | ||
869 | * This function will set the X.509 certificate's subject key ID extension. | ||
870 | * | ||
871 | * Returns 0 on success, or a negative value in case of an error. | ||
872 | * | ||
873 | **/ | ||
874 | int | ||
875 | gnutls_x509_crt_set_subject_key_id (gnutls_x509_crt_t cert, | ||
876 | const void *id, size_t id_size) | ||
877 | { | ||
878 | int result; | ||
879 | gnutls_datum_t old_id, der_data; | ||
880 | unsigned int critical; | ||
881 | |||
882 | if (cert == NULL) | ||
883 | { | ||
884 | gnutls_assert (); | ||
885 | return GNUTLS_E_INVALID_REQUEST; | ||
886 | } | ||
887 | |||
888 | /* Check if the extension already exists. | ||
889 | */ | ||
890 | result = | ||
891 | _gnutls_x509_crt_get_extension (cert, "2.5.29.14", 0, &old_id, &critical); | ||
892 | |||
893 | if (result >= 0) | ||
894 | _gnutls_free_datum (&old_id); | ||
895 | if (result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) | ||
896 | { | ||
897 | gnutls_assert (); | ||
898 | return GNUTLS_E_INVALID_REQUEST; | ||
899 | } | ||
900 | |||
901 | /* generate the extension. | ||
902 | */ | ||
903 | result = _gnutls_x509_ext_gen_key_id (id, id_size, &der_data); | ||
904 | if (result < 0) | ||
905 | { | ||
906 | gnutls_assert (); | ||
907 | return result; | ||
908 | } | ||
909 | |||
910 | result = _gnutls_x509_crt_set_extension (cert, "2.5.29.14", &der_data, 0); | ||
911 | |||
912 | _gnutls_free_datum (&der_data); | ||
913 | |||
914 | if (result < 0) | ||
915 | { | ||
916 | gnutls_assert (); | ||
917 | return result; | ||
918 | } | ||
919 | |||
920 | cert->use_extensions = 1; | ||
921 | |||
922 | return 0; | ||
923 | } | ||
924 | |||
925 | /** | ||
926 | * gnutls_x509_crt_set_authority_key_id - This function will set the certificate authority's key id | ||
927 | * @cert: should contain a gnutls_x509_crt_t structure | ||
928 | * @id: The key ID | ||
929 | * @id_size: Holds the size of the serial field. | ||
930 | * | ||
931 | * This function will set the X.509 certificate's authority key ID extension. | ||
932 | * Only the keyIdentifier field can be set with this function. | ||
933 | * | ||
934 | * Returns 0 on success, or a negative value in case of an error. | ||
935 | * | ||
936 | **/ | ||
937 | int | ||
938 | gnutls_x509_crt_set_authority_key_id (gnutls_x509_crt_t cert, | ||
939 | const void *id, size_t id_size) | ||
940 | { | ||
941 | int result; | ||
942 | gnutls_datum_t old_id, der_data; | ||
943 | unsigned int critical; | ||
944 | |||
945 | if (cert == NULL) | ||
946 | { | ||
947 | gnutls_assert (); | ||
948 | return GNUTLS_E_INVALID_REQUEST; | ||
949 | } | ||
950 | |||
951 | /* Check if the extension already exists. | ||
952 | */ | ||
953 | result = | ||
954 | _gnutls_x509_crt_get_extension (cert, "2.5.29.35", 0, &old_id, &critical); | ||
955 | |||
956 | if (result >= 0) | ||
957 | _gnutls_free_datum (&old_id); | ||
958 | if (result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) | ||
959 | { | ||
960 | gnutls_assert (); | ||
961 | return GNUTLS_E_INVALID_REQUEST; | ||
962 | } | ||
963 | |||
964 | /* generate the extension. | ||
965 | */ | ||
966 | result = _gnutls_x509_ext_gen_auth_key_id (id, id_size, &der_data); | ||
967 | if (result < 0) | ||
968 | { | ||
969 | gnutls_assert (); | ||
970 | return result; | ||
971 | } | ||
972 | |||
973 | result = _gnutls_x509_crt_set_extension (cert, "2.5.29.35", &der_data, 0); | ||
974 | |||
975 | _gnutls_free_datum (&der_data); | ||
976 | |||
977 | if (result < 0) | ||
978 | { | ||
979 | gnutls_assert (); | ||
980 | return result; | ||
981 | } | ||
982 | |||
983 | cert->use_extensions = 1; | ||
984 | |||
985 | return 0; | ||
986 | } | ||
987 | |||
988 | /** | ||
989 | * gnutls_x509_crt_set_key_purpose_oid - This function sets the Certificate's key purpose OIDs | ||
990 | * @cert: should contain a gnutls_x509_crt_t structure | ||
991 | * @oid: a pointer to a null terminated string that holds the OID | ||
992 | * @critical: Whether this extension will be critical or not | ||
993 | * | ||
994 | * This function will set the key purpose OIDs of the Certificate. | ||
995 | * These are stored in the Extended Key Usage extension (2.5.29.37) | ||
996 | * See the GNUTLS_KP_* definitions for human readable names. | ||
997 | * | ||
998 | * Subsequent calls to this function will append OIDs to the OID list. | ||
999 | * | ||
1000 | * On success 0 is returned. | ||
1001 | * | ||
1002 | **/ | ||
1003 | int | ||
1004 | gnutls_x509_crt_set_key_purpose_oid (gnutls_x509_crt_t cert, | ||
1005 | const void *oid, unsigned int critical) | ||
1006 | { | ||
1007 | int result; | ||
1008 | gnutls_datum_t old_id, der_data; | ||
1009 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY; | ||
1010 | |||
1011 | if (cert == NULL) | ||
1012 | { | ||
1013 | gnutls_assert (); | ||
1014 | return GNUTLS_E_INVALID_REQUEST; | ||
1015 | } | ||
1016 | |||
1017 | result = asn1_create_element | ||
1018 | (_gnutls_get_pkix (), "PKIX1.ExtKeyUsageSyntax", &c2); | ||
1019 | if (result != ASN1_SUCCESS) | ||
1020 | { | ||
1021 | gnutls_assert (); | ||
1022 | return _gnutls_asn2err (result); | ||
1023 | } | ||
1024 | |||
1025 | /* Check if the extension already exists. | ||
1026 | */ | ||
1027 | result = | ||
1028 | _gnutls_x509_crt_get_extension (cert, "2.5.29.37", 0, &old_id, NULL); | ||
1029 | |||
1030 | if (result >= 0) | ||
1031 | { | ||
1032 | /* decode it. | ||
1033 | */ | ||
1034 | result = asn1_der_decoding (&c2, old_id.data, old_id.size, NULL); | ||
1035 | _gnutls_free_datum (&old_id); | ||
1036 | |||
1037 | if (result != ASN1_SUCCESS) | ||
1038 | { | ||
1039 | gnutls_assert (); | ||
1040 | asn1_delete_structure (&c2); | ||
1041 | return _gnutls_asn2err (result); | ||
1042 | } | ||
1043 | |||
1044 | } | ||
1045 | |||
1046 | /* generate the extension. | ||
1047 | */ | ||
1048 | /* 1. create a new element. | ||
1049 | */ | ||
1050 | result = asn1_write_value (c2, "", "NEW", 1); | ||
1051 | if (result != ASN1_SUCCESS) | ||
1052 | { | ||
1053 | gnutls_assert (); | ||
1054 | asn1_delete_structure (&c2); | ||
1055 | return _gnutls_asn2err (result); | ||
1056 | } | ||
1057 | |||
1058 | /* 2. Add the OID. | ||
1059 | */ | ||
1060 | result = asn1_write_value (c2, "?LAST", oid, 1); | ||
1061 | if (result != ASN1_SUCCESS) | ||
1062 | { | ||
1063 | gnutls_assert (); | ||
1064 | asn1_delete_structure (&c2); | ||
1065 | return _gnutls_asn2err (result); | ||
1066 | } | ||
1067 | |||
1068 | result = _gnutls_x509_der_encode (c2, "", &der_data, 0); | ||
1069 | asn1_delete_structure (&c2); | ||
1070 | |||
1071 | if (result != ASN1_SUCCESS) | ||
1072 | { | ||
1073 | gnutls_assert (); | ||
1074 | return _gnutls_asn2err (result); | ||
1075 | } | ||
1076 | |||
1077 | result = _gnutls_x509_crt_set_extension (cert, "2.5.29.37", | ||
1078 | &der_data, critical); | ||
1079 | |||
1080 | _gnutls_free_datum (&der_data); | ||
1081 | |||
1082 | if (result < 0) | ||
1083 | { | ||
1084 | gnutls_assert (); | ||
1085 | return result; | ||
1086 | } | ||
1087 | |||
1088 | cert->use_extensions = 1; | ||
1089 | |||
1090 | return 0; | ||
1091 | |||
1092 | } | ||
1093 | |||
1094 | #endif /* ENABLE_PKI */ | ||