1 /*
2 * Copyright (C) 2014-2016 Free Software Foundation, Inc.
3 * Copyright (C) 2016 Red Hat, Inc.
4 *
5 * This file is part of GnuTLS.
6 *
7 * The GnuTLS 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 License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>
19 *
20 */
21
22 /* This file contains functions to handle X.509 certificate extensions (the x509-ext API)
23 */
24
25 #include "gnutls_int.h"
26 #include <datum.h>
27 #include "errors.h"
28 #include <common.h>
29 #include <x509.h>
30 #include <x509_b64.h>
31 #include "x509_ext_int.h"
32 #include "virt-san.h"
33 #include <gnutls/x509-ext.h>
34
35 #define MAX_ENTRIES 64
36 struct gnutls_subject_alt_names_st {
37 struct name_st *names;
38 unsigned int size;
39 };
40
41 /**
42 * gnutls_subject_alt_names_init:
43 * @sans: The alternative names
44 *
45 * This function will initialize an alternative names structure.
46 *
47 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
48 *
49 * Since: 3.3.0
50 **/
gnutls_subject_alt_names_init(gnutls_subject_alt_names_t * sans)51 int gnutls_subject_alt_names_init(gnutls_subject_alt_names_t * sans)
52 {
53 *sans = gnutls_calloc(1, sizeof(struct gnutls_subject_alt_names_st));
54 if (*sans == NULL) {
55 gnutls_assert();
56 return GNUTLS_E_MEMORY_ERROR;
57 }
58
59 return 0;
60 }
61
subject_alt_names_deinit(gnutls_subject_alt_names_t sans)62 static void subject_alt_names_deinit(gnutls_subject_alt_names_t sans)
63 {
64 unsigned int i;
65
66 for (i = 0; i < sans->size; i++) {
67 gnutls_free(sans->names[i].san.data);
68 gnutls_free(sans->names[i].othername_oid.data);
69 }
70 gnutls_free(sans->names);
71 }
72
73 /**
74 * gnutls_subject_alt_names_deinit:
75 * @sans: The alternative names
76 *
77 * This function will deinitialize an alternative names structure.
78 *
79 * Since: 3.3.0
80 **/
gnutls_subject_alt_names_deinit(gnutls_subject_alt_names_t sans)81 void gnutls_subject_alt_names_deinit(gnutls_subject_alt_names_t sans)
82 {
83 subject_alt_names_deinit(sans);
84 gnutls_free(sans);
85 }
86
87 /**
88 * gnutls_subject_alt_names_get:
89 * @sans: The alternative names
90 * @seq: The index of the name to get
91 * @san_type: Will hold the type of the name (of %gnutls_subject_alt_names_t)
92 * @san: The alternative name data (should be treated as constant)
93 * @othername_oid: The object identifier if @san_type is %GNUTLS_SAN_OTHERNAME (should be treated as constant)
94 *
95 * This function will return a specific alternative name as stored in
96 * the @sans type. The returned values should be treated as constant
97 * and valid for the lifetime of @sans.
98 *
99 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
100 * if the index is out of bounds, otherwise a negative error value.
101 *
102 * Since: 3.3.0
103 **/
gnutls_subject_alt_names_get(gnutls_subject_alt_names_t sans,unsigned int seq,unsigned int * san_type,gnutls_datum_t * san,gnutls_datum_t * othername_oid)104 int gnutls_subject_alt_names_get(gnutls_subject_alt_names_t sans,
105 unsigned int seq, unsigned int *san_type,
106 gnutls_datum_t * san,
107 gnutls_datum_t * othername_oid)
108 {
109 if (seq >= sans->size)
110 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
111
112 if (san) {
113 memcpy(san, &sans->names[seq].san, sizeof(gnutls_datum_t));
114 }
115
116 if (san_type)
117 *san_type = sans->names[seq].type;
118
119 if (othername_oid != NULL && sans->names[seq].type == GNUTLS_SAN_OTHERNAME) {
120 othername_oid->data = sans->names[seq].othername_oid.data;
121 othername_oid->size = sans->names[seq].othername_oid.size;
122 }
123
124 return 0;
125 }
126
127 /* This is the same as gnutls_subject_alt_names_set() but will not
128 * copy the strings. It expects all the provided input to be already
129 * allocated by gnutls. */
130 static
subject_alt_names_set(struct name_st ** names,unsigned int * size,unsigned int san_type,gnutls_datum_t * san,char * othername_oid,unsigned raw)131 int subject_alt_names_set(struct name_st **names,
132 unsigned int *size,
133 unsigned int san_type,
134 gnutls_datum_t * san, char *othername_oid,
135 unsigned raw)
136 {
137 void *tmp;
138 int ret;
139
140 tmp = gnutls_realloc(*names, (*size + 1) * sizeof((*names)[0]));
141 if (tmp == NULL) {
142 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
143 }
144 *names = tmp;
145
146 ret = _gnutls_alt_name_assign_virt_type(&(*names)[*size], san_type, san, othername_oid, raw);
147 if (ret < 0)
148 return gnutls_assert_val(ret);
149
150 (*size)++;
151 return 0;
152 }
153
154 /**
155 * gnutls_subject_alt_names_set:
156 * @sans: The alternative names
157 * @san_type: The type of the name (of %gnutls_subject_alt_names_t)
158 * @san: The alternative name data
159 * @othername_oid: The object identifier if @san_type is %GNUTLS_SAN_OTHERNAME
160 *
161 * This function will store the specified alternative name in
162 * the @sans.
163 *
164 * Since version 3.5.7 the %GNUTLS_SAN_RFC822NAME, %GNUTLS_SAN_DNSNAME, and
165 * %GNUTLS_SAN_OTHERNAME_XMPP are converted to ACE format when necessary.
166 *
167 * Returns: On success, %GNUTLS_E_SUCCESS (0), otherwise a negative error value.
168 *
169 * Since: 3.3.0
170 **/
gnutls_subject_alt_names_set(gnutls_subject_alt_names_t sans,unsigned int san_type,const gnutls_datum_t * san,const char * othername_oid)171 int gnutls_subject_alt_names_set(gnutls_subject_alt_names_t sans,
172 unsigned int san_type,
173 const gnutls_datum_t * san,
174 const char *othername_oid)
175 {
176 int ret;
177 gnutls_datum_t copy;
178 char *ooc;
179
180 ret = _gnutls_set_strdatum(©, san->data, san->size);
181 if (ret < 0)
182 return gnutls_assert_val(ret);
183
184 if (othername_oid != NULL)
185 ooc = gnutls_strdup(othername_oid);
186 else
187 ooc = NULL;
188 ret = subject_alt_names_set(&sans->names, &sans->size,
189 san_type, ©, ooc, 0);
190 if (ret < 0) {
191 gnutls_free(copy.data);
192 return gnutls_assert_val(ret);
193 }
194
195 return 0;
196 }
197
198 /**
199 * gnutls_x509_ext_import_subject_alt_names:
200 * @ext: The DER-encoded extension data
201 * @sans: The alternative names
202 * @flags: should be zero
203 *
204 * This function will export the alternative names in the provided DER-encoded
205 * SubjectAltName PKIX extension, to a %gnutls_subject_alt_names_t type. @sans
206 * must be initialized.
207 *
208 * This function will succeed even if there no subject alternative names
209 * in the structure.
210 *
211 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
212 *
213 * Since: 3.3.0
214 **/
gnutls_x509_ext_import_subject_alt_names(const gnutls_datum_t * ext,gnutls_subject_alt_names_t sans,unsigned int flags)215 int gnutls_x509_ext_import_subject_alt_names(const gnutls_datum_t * ext,
216 gnutls_subject_alt_names_t sans,
217 unsigned int flags)
218 {
219 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
220 int result, ret;
221 unsigned int i;
222 gnutls_datum_t san, othername_oid;
223 unsigned type;
224
225 result =
226 asn1_create_element(_gnutls_get_pkix(), "PKIX1.GeneralNames", &c2);
227 if (result != ASN1_SUCCESS) {
228 gnutls_assert();
229 return _gnutls_asn2err(result);
230 }
231
232 result = _asn1_strict_der_decode(&c2, ext->data, ext->size, NULL);
233 if (result != ASN1_SUCCESS) {
234 gnutls_assert();
235 ret = _gnutls_asn2err(result);
236 goto cleanup;
237 }
238
239 for (i=0;;i++) {
240 san.data = NULL;
241 san.size = 0;
242 othername_oid.data = NULL;
243
244 ret = _gnutls_parse_general_name2(c2, "", i, &san, &type, 0);
245 if (ret < 0)
246 break;
247
248 if (type == GNUTLS_SAN_OTHERNAME) {
249 ret =
250 _gnutls_parse_general_name2(c2, "", i,
251 &othername_oid,
252 NULL, 1);
253 if (ret < 0)
254 break;
255
256 } else if (san.size == 0 || san.data == NULL) {
257 ret = gnutls_assert_val(GNUTLS_E_X509_UNKNOWN_SAN);
258 break;
259 }
260
261 ret = subject_alt_names_set(&sans->names, &sans->size,
262 type, &san,
263 (char *)othername_oid.data, 1);
264 if (ret < 0)
265 break;
266 }
267
268 sans->size = i;
269 if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
270 gnutls_free(san.data);
271 gnutls_free(othername_oid.data);
272 gnutls_assert();
273 goto cleanup;
274 }
275
276 ret = 0;
277 cleanup:
278 asn1_delete_structure(&c2);
279 return ret;
280 }
281
282 /**
283 * gnutls_x509_ext_export_subject_alt_names:
284 * @sans: The alternative names
285 * @ext: The DER-encoded extension data; must be freed using gnutls_free().
286 *
287 * This function will convert the provided alternative names structure to a
288 * DER-encoded SubjectAltName PKIX extension. The output data in @ext will be allocated using
289 * gnutls_malloc().
290 *
291 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
292 *
293 * Since: 3.3.0
294 **/
gnutls_x509_ext_export_subject_alt_names(gnutls_subject_alt_names_t sans,gnutls_datum_t * ext)295 int gnutls_x509_ext_export_subject_alt_names(gnutls_subject_alt_names_t sans,
296 gnutls_datum_t * ext)
297 {
298 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
299 int result, ret;
300 unsigned i;
301
302 result =
303 asn1_create_element(_gnutls_get_pkix(), "PKIX1.GeneralNames", &c2);
304 if (result != ASN1_SUCCESS) {
305 gnutls_assert();
306 return _gnutls_asn2err(result);
307 }
308
309 for (i = 0; i < sans->size; i++) {
310 if (sans->names[i].type == GNUTLS_SAN_OTHERNAME) {
311 ret = _gnutls_write_new_othername(c2, "", (char*)sans->names[i].othername_oid.data,
312 sans->names[i].san.data, sans->names[i].san.size);
313 } else {
314 ret =
315 _gnutls_write_new_general_name(c2, "", sans->names[i].type,
316 sans->names[i].san.data,
317 sans->names[i].san.size);
318 }
319
320 if (ret < 0) {
321 gnutls_assert();
322 goto cleanup;
323 }
324 }
325
326 ret = _gnutls_x509_der_encode(c2, "", ext, 0);
327 if (ret < 0) {
328 gnutls_assert();
329 goto cleanup;
330 }
331
332 ret = 0;
333
334 cleanup:
335 asn1_delete_structure(&c2);
336 return ret;
337 }
338
339 /**
340 * gnutls_x509_ext_import_name_constraints:
341 * @ext: a DER encoded extension
342 * @nc: The nameconstraints
343 * @flags: zero or %GNUTLS_NAME_CONSTRAINTS_FLAG_APPEND
344 *
345 * This function will return an intermediate type containing
346 * the name constraints of the provided NameConstraints extension. That
347 * can be used in combination with gnutls_x509_name_constraints_check()
348 * to verify whether a server's name is in accordance with the constraints.
349 *
350 * When the @flags is set to %GNUTLS_NAME_CONSTRAINTS_FLAG_APPEND, then if
351 * the @nc type is empty this function will behave identically as if the flag was not set.
352 * Otherwise if there are elements in the @nc structure then the
353 * constraints will be merged with the existing constraints following
354 * RFC5280 p6.1.4 (excluded constraints will be appended, permitted
355 * will be intersected).
356 *
357 * Note that @nc must be initialized prior to calling this function.
358 *
359 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
360 * if the extension is not present, otherwise a negative error value.
361 *
362 * Since: 3.3.0
363 **/
gnutls_x509_ext_import_name_constraints(const gnutls_datum_t * ext,gnutls_x509_name_constraints_t nc,unsigned int flags)364 int gnutls_x509_ext_import_name_constraints(const gnutls_datum_t * ext,
365 gnutls_x509_name_constraints_t nc,
366 unsigned int flags)
367 {
368 int result, ret;
369 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
370 gnutls_x509_name_constraints_t nc2 = NULL;
371
372 result = asn1_create_element
373 (_gnutls_get_pkix(), "PKIX1.NameConstraints", &c2);
374 if (result != ASN1_SUCCESS) {
375 gnutls_assert();
376 return _gnutls_asn2err(result);
377 }
378
379 result = _asn1_strict_der_decode(&c2, ext->data, ext->size, NULL);
380 if (result != ASN1_SUCCESS) {
381 gnutls_assert();
382 ret = _gnutls_asn2err(result);
383 goto cleanup;
384 }
385
386 if (flags & GNUTLS_NAME_CONSTRAINTS_FLAG_APPEND &&
387 (nc->permitted != NULL || nc->excluded != NULL)) {
388 ret = gnutls_x509_name_constraints_init (&nc2);
389 if (ret < 0) {
390 gnutls_assert();
391 goto cleanup;
392 }
393
394 ret =
395 _gnutls_extract_name_constraints(c2, "permittedSubtrees",
396 &nc2->permitted);
397 if (ret < 0) {
398 gnutls_assert();
399 goto cleanup;
400 }
401
402 ret =
403 _gnutls_extract_name_constraints(c2, "excludedSubtrees",
404 &nc2->excluded);
405 if (ret < 0) {
406 gnutls_assert();
407 goto cleanup;
408 }
409
410 ret = _gnutls_x509_name_constraints_merge(nc, nc2);
411 if (ret < 0) {
412 gnutls_assert();
413 goto cleanup;
414 }
415 } else {
416 _gnutls_name_constraints_node_free(nc->permitted);
417 _gnutls_name_constraints_node_free(nc->excluded);
418
419 ret =
420 _gnutls_extract_name_constraints(c2, "permittedSubtrees",
421 &nc->permitted);
422 if (ret < 0) {
423 gnutls_assert();
424 goto cleanup;
425 }
426
427 ret =
428 _gnutls_extract_name_constraints(c2, "excludedSubtrees",
429 &nc->excluded);
430 if (ret < 0) {
431 gnutls_assert();
432 goto cleanup;
433 }
434 }
435
436 ret = 0;
437
438 cleanup:
439 asn1_delete_structure(&c2);
440 if (nc2)
441 gnutls_x509_name_constraints_deinit (nc2);
442
443 return ret;
444 }
445
446 /**
447 * gnutls_x509_ext_export_name_constraints:
448 * @nc: The nameconstraints
449 * @ext: The DER-encoded extension data; must be freed using gnutls_free().
450 *
451 * This function will convert the provided name constraints type to a
452 * DER-encoded PKIX NameConstraints (2.5.29.30) extension. The output data in
453 * @ext will be allocated using gnutls_malloc().
454 *
455 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
456 *
457 * Since: 3.3.0
458 **/
gnutls_x509_ext_export_name_constraints(gnutls_x509_name_constraints_t nc,gnutls_datum_t * ext)459 int gnutls_x509_ext_export_name_constraints(gnutls_x509_name_constraints_t nc,
460 gnutls_datum_t * ext)
461 {
462 int ret, result;
463 uint8_t null = 0;
464 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
465 struct name_constraints_node_st *tmp;
466
467 if (nc->permitted == NULL && nc->excluded == NULL)
468 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
469
470 result = asn1_create_element
471 (_gnutls_get_pkix(), "PKIX1.NameConstraints", &c2);
472 if (result != ASN1_SUCCESS) {
473 gnutls_assert();
474 return _gnutls_asn2err(result);
475 }
476
477 if (nc->permitted == NULL) {
478 (void)asn1_write_value(c2, "permittedSubtrees", NULL, 0);
479 } else {
480 tmp = nc->permitted;
481 do {
482 result =
483 asn1_write_value(c2, "permittedSubtrees", "NEW", 1);
484 if (result != ASN1_SUCCESS) {
485 gnutls_assert();
486 ret = _gnutls_asn2err(result);
487 goto cleanup;
488 }
489
490 result =
491 asn1_write_value(c2,
492 "permittedSubtrees.?LAST.maximum",
493 NULL, 0);
494 if (result != ASN1_SUCCESS) {
495 gnutls_assert();
496 ret = _gnutls_asn2err(result);
497 goto cleanup;
498 }
499
500 result =
501 asn1_write_value(c2,
502 "permittedSubtrees.?LAST.minimum",
503 &null, 1);
504 if (result != ASN1_SUCCESS) {
505 gnutls_assert();
506 ret = _gnutls_asn2err(result);
507 goto cleanup;
508 }
509
510 ret =
511 _gnutls_write_general_name(c2,
512 "permittedSubtrees.?LAST.base",
513 tmp->type,
514 tmp->name.data,
515 tmp->name.size);
516 if (ret < 0) {
517 gnutls_assert();
518 goto cleanup;
519 }
520 tmp = tmp->next;
521 } while (tmp != NULL);
522 }
523
524 if (nc->excluded == NULL) {
525 (void)asn1_write_value(c2, "excludedSubtrees", NULL, 0);
526 } else {
527 tmp = nc->excluded;
528 do {
529 result =
530 asn1_write_value(c2, "excludedSubtrees", "NEW", 1);
531 if (result != ASN1_SUCCESS) {
532 gnutls_assert();
533 ret = _gnutls_asn2err(result);
534 goto cleanup;
535 }
536
537 result =
538 asn1_write_value(c2,
539 "excludedSubtrees.?LAST.maximum",
540 NULL, 0);
541 if (result != ASN1_SUCCESS) {
542 gnutls_assert();
543 ret = _gnutls_asn2err(result);
544 goto cleanup;
545 }
546
547 result =
548 asn1_write_value(c2,
549 "excludedSubtrees.?LAST.minimum",
550 &null, 1);
551 if (result != ASN1_SUCCESS) {
552 gnutls_assert();
553 ret = _gnutls_asn2err(result);
554 goto cleanup;
555 }
556
557 ret =
558 _gnutls_write_general_name(c2,
559 "excludedSubtrees.?LAST.base",
560 tmp->type,
561 tmp->name.data,
562 tmp->name.size);
563 if (ret < 0) {
564 gnutls_assert();
565 goto cleanup;
566 }
567 tmp = tmp->next;
568 } while (tmp != NULL);
569
570 }
571
572 ret = _gnutls_x509_der_encode(c2, "", ext, 0);
573 if (ret < 0) {
574 gnutls_assert();
575 goto cleanup;
576 }
577
578 ret = 0;
579
580 cleanup:
581 asn1_delete_structure(&c2);
582 return ret;
583 }
584
585 /**
586 * gnutls_x509_ext_import_subject_key_id:
587 * @ext: a DER encoded extension
588 * @id: will contain the subject key ID
589 *
590 * This function will return the subject key ID stored in the provided
591 * SubjectKeyIdentifier extension. The ID will be allocated using
592 * gnutls_malloc().
593 *
594 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
595 * if the extension is not present, otherwise a negative error value.
596 *
597 * Since: 3.3.0
598 **/
gnutls_x509_ext_import_subject_key_id(const gnutls_datum_t * ext,gnutls_datum_t * id)599 int gnutls_x509_ext_import_subject_key_id(const gnutls_datum_t * ext,
600 gnutls_datum_t * id)
601 {
602 int result, ret;
603 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
604
605 if (ext->size == 0 || ext->data == NULL) {
606 gnutls_assert();
607 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
608 }
609
610 result = asn1_create_element
611 (_gnutls_get_pkix(), "PKIX1.SubjectKeyIdentifier", &c2);
612 if (result != ASN1_SUCCESS) {
613 gnutls_assert();
614 return _gnutls_asn2err(result);
615 }
616
617 result = _asn1_strict_der_decode(&c2, ext->data, ext->size, NULL);
618 if (result != ASN1_SUCCESS) {
619 gnutls_assert();
620 ret = _gnutls_asn2err(result);
621 goto cleanup;
622 }
623
624 ret = _gnutls_x509_read_value(c2, "", id);
625 if (ret < 0) {
626 gnutls_assert();
627 goto cleanup;
628 }
629
630 ret = 0;
631 cleanup:
632 asn1_delete_structure(&c2);
633
634 return ret;
635
636 }
637
638 /**
639 * gnutls_x509_ext_export_subject_key_id:
640 * @id: The key identifier
641 * @ext: The DER-encoded extension data; must be freed using gnutls_free().
642 *
643 * This function will convert the provided key identifier to a
644 * DER-encoded PKIX SubjectKeyIdentifier extension.
645 * The output data in @ext will be allocated using
646 * gnutls_malloc().
647 *
648 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
649 *
650 * Since: 3.3.0
651 **/
gnutls_x509_ext_export_subject_key_id(const gnutls_datum_t * id,gnutls_datum_t * ext)652 int gnutls_x509_ext_export_subject_key_id(const gnutls_datum_t * id,
653 gnutls_datum_t * ext)
654 {
655 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
656 int ret, result;
657
658 result =
659 asn1_create_element(_gnutls_get_pkix(),
660 "PKIX1.SubjectKeyIdentifier", &c2);
661 if (result != ASN1_SUCCESS) {
662 gnutls_assert();
663 return _gnutls_asn2err(result);
664 }
665
666 result = asn1_write_value(c2, "", id->data, id->size);
667 if (result != ASN1_SUCCESS) {
668 gnutls_assert();
669 ret = _gnutls_asn2err(result);
670 goto cleanup;
671 }
672
673 ret = _gnutls_x509_der_encode(c2, "", ext, 0);
674 if (ret < 0) {
675 gnutls_assert();
676 goto cleanup;
677 }
678
679 ret = 0;
680 cleanup:
681 asn1_delete_structure(&c2);
682 return ret;
683 }
684
685 struct gnutls_x509_aki_st {
686 gnutls_datum_t id;
687 struct gnutls_subject_alt_names_st cert_issuer;
688 gnutls_datum_t serial;
689 };
690
691 /**
692 * gnutls_x509_aki_init:
693 * @aki: The authority key ID type
694 *
695 * This function will initialize an authority key ID.
696 *
697 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
698 *
699 * Since: 3.3.0
700 **/
gnutls_x509_aki_init(gnutls_x509_aki_t * aki)701 int gnutls_x509_aki_init(gnutls_x509_aki_t * aki)
702 {
703 *aki = gnutls_calloc(1, sizeof(struct gnutls_x509_aki_st));
704 if (*aki == NULL)
705 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
706
707 return 0;
708 }
709
710 /**
711 * gnutls_x509_aki_deinit:
712 * @aki: The authority key identifier type
713 *
714 * This function will deinitialize an authority key identifier.
715 *
716 * Since: 3.3.0
717 **/
gnutls_x509_aki_deinit(gnutls_x509_aki_t aki)718 void gnutls_x509_aki_deinit(gnutls_x509_aki_t aki)
719 {
720 gnutls_free(aki->serial.data);
721 gnutls_free(aki->id.data);
722 subject_alt_names_deinit(&aki->cert_issuer);
723 gnutls_free(aki);
724 }
725
726 /**
727 * gnutls_x509_aki_get_id:
728 * @aki: The authority key ID
729 * @id: Will hold the identifier
730 *
731 * This function will return the key identifier as stored in
732 * the @aki type. The identifier should be treated as constant.
733 *
734 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
735 * if the index is out of bounds, otherwise a negative error value.
736 *
737 * Since: 3.3.0
738 **/
gnutls_x509_aki_get_id(gnutls_x509_aki_t aki,gnutls_datum_t * id)739 int gnutls_x509_aki_get_id(gnutls_x509_aki_t aki, gnutls_datum_t * id)
740 {
741 if (aki->id.size == 0)
742 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
743
744 memcpy(id, &aki->id, sizeof(gnutls_datum_t));
745 return 0;
746 }
747
748 /**
749 * gnutls_x509_aki_set_id:
750 * @aki: The authority key ID
751 * @id: the key identifier
752 *
753 * This function will set the keyIdentifier to be stored in the @aki
754 * type.
755 *
756 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
757 *
758 * Since: 3.3.0
759 **/
gnutls_x509_aki_set_id(gnutls_x509_aki_t aki,const gnutls_datum_t * id)760 int gnutls_x509_aki_set_id(gnutls_x509_aki_t aki, const gnutls_datum_t * id)
761 {
762 return _gnutls_set_datum(&aki->id, id->data, id->size);
763 }
764
765 /**
766 * gnutls_x509_aki_set_cert_issuer:
767 * @aki: The authority key ID
768 * @san_type: the type of the name (of %gnutls_subject_alt_names_t), may be null
769 * @san: The alternative name data
770 * @othername_oid: The object identifier if @san_type is %GNUTLS_SAN_OTHERNAME
771 * @serial: The authorityCertSerialNumber number (may be null)
772 *
773 * This function will set the authorityCertIssuer name and the authorityCertSerialNumber
774 * to be stored in the @aki type. When storing multiple names, the serial
775 * should be set on the first call, and subsequent calls should use a %NULL serial.
776 *
777 * Since version 3.5.7 the %GNUTLS_SAN_RFC822NAME, %GNUTLS_SAN_DNSNAME, and
778 * %GNUTLS_SAN_OTHERNAME_XMPP are converted to ACE format when necessary.
779 *
780 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
781 *
782 * Since: 3.3.0
783 **/
gnutls_x509_aki_set_cert_issuer(gnutls_x509_aki_t aki,unsigned int san_type,const gnutls_datum_t * san,const char * othername_oid,const gnutls_datum_t * serial)784 int gnutls_x509_aki_set_cert_issuer(gnutls_x509_aki_t aki,
785 unsigned int san_type,
786 const gnutls_datum_t *san,
787 const char *othername_oid,
788 const gnutls_datum_t *serial)
789 {
790 int ret;
791 gnutls_datum_t t_san, t_othername_oid = { NULL, 0 };
792
793 ret = _gnutls_set_datum(&aki->serial, serial->data, serial->size);
794 if (ret < 0)
795 return gnutls_assert_val(ret);
796
797 aki->cert_issuer.names[aki->cert_issuer.size].type = san_type;
798
799 ret = _gnutls_set_strdatum(&t_san, san->data, san->size);
800 if (ret < 0)
801 return gnutls_assert_val(ret);
802
803 if (othername_oid) {
804 t_othername_oid.data = (uint8_t *) gnutls_strdup(othername_oid);
805 if (t_othername_oid.data == NULL) {
806 gnutls_free(t_san.data);
807 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
808 }
809 t_othername_oid.size = strlen(othername_oid);
810 }
811
812 ret =
813 subject_alt_names_set(&aki->cert_issuer.names,
814 &aki->cert_issuer.size, san_type, &t_san,
815 (char *)t_othername_oid.data, 0);
816 if (ret < 0) {
817 gnutls_assert();
818 return ret;
819 }
820
821 return 0;
822 }
823
824 /**
825 * gnutls_x509_aki_get_cert_issuer:
826 * @aki: The authority key ID
827 * @seq: The index of the name to get
828 * @san_type: Will hold the type of the name (of %gnutls_subject_alt_names_t)
829 * @san: The alternative name data
830 * @othername_oid: The object identifier if @san_type is %GNUTLS_SAN_OTHERNAME
831 * @serial: The authorityCertSerialNumber number
832 *
833 * This function will return a specific authorityCertIssuer name as stored in
834 * the @aki type, as well as the authorityCertSerialNumber. All the returned
835 * values should be treated as constant, and may be set to %NULL when are not required.
836 *
837 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
838 * if the index is out of bounds, otherwise a negative error value.
839 *
840 * Since: 3.3.0
841 **/
gnutls_x509_aki_get_cert_issuer(gnutls_x509_aki_t aki,unsigned int seq,unsigned int * san_type,gnutls_datum_t * san,gnutls_datum_t * othername_oid,gnutls_datum_t * serial)842 int gnutls_x509_aki_get_cert_issuer(gnutls_x509_aki_t aki, unsigned int seq,
843 unsigned int *san_type,
844 gnutls_datum_t *san,
845 gnutls_datum_t *othername_oid,
846 gnutls_datum_t *serial)
847 {
848 if (seq >= aki->cert_issuer.size)
849 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
850
851 if (aki->serial.size == 0)
852 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
853
854 if (serial)
855 memcpy(serial, &aki->serial, sizeof(gnutls_datum_t));
856
857 if (san) {
858 memcpy(san, &aki->cert_issuer.names[seq].san,
859 sizeof(gnutls_datum_t));
860 }
861
862 if (othername_oid != NULL
863 && aki->cert_issuer.names[seq].type == GNUTLS_SAN_OTHERNAME) {
864 othername_oid->data =
865 aki->cert_issuer.names[seq].othername_oid.data;
866 othername_oid->size =
867 aki->cert_issuer.names[seq].othername_oid.size;
868 }
869
870 if (san_type)
871 *san_type = aki->cert_issuer.names[seq].type;
872
873 return 0;
874
875 }
876
877 /**
878 * gnutls_x509_ext_import_authority_key_id:
879 * @ext: a DER encoded extension
880 * @aki: An initialized authority key identifier type
881 * @flags: should be zero
882 *
883 * This function will return the subject key ID stored in the provided
884 * AuthorityKeyIdentifier extension.
885 *
886 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
887 * if the extension is not present, otherwise a negative error value.
888 *
889 * Since: 3.3.0
890 **/
gnutls_x509_ext_import_authority_key_id(const gnutls_datum_t * ext,gnutls_x509_aki_t aki,unsigned int flags)891 int gnutls_x509_ext_import_authority_key_id(const gnutls_datum_t * ext,
892 gnutls_x509_aki_t aki,
893 unsigned int flags)
894 {
895 int ret;
896 unsigned i;
897 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
898 gnutls_datum_t san, othername_oid;
899 unsigned type;
900
901 ret = asn1_create_element
902 (_gnutls_get_pkix(), "PKIX1.AuthorityKeyIdentifier", &c2);
903 if (ret != ASN1_SUCCESS) {
904 gnutls_assert();
905 return _gnutls_asn2err(ret);
906 }
907
908 ret = _asn1_strict_der_decode(&c2, ext->data, ext->size, NULL);
909 if (ret != ASN1_SUCCESS) {
910 gnutls_assert();
911 ret = _gnutls_asn2err(ret);
912 goto cleanup;
913 }
914
915 /* Read authorityCertIssuer */
916 for (i=0;;i++) {
917 san.data = NULL;
918 san.size = 0;
919 othername_oid.data = NULL;
920
921 ret = _gnutls_parse_general_name2(c2, "authorityCertIssuer", i,
922 &san, &type, 0);
923 if (ret < 0)
924 break;
925
926 if (type == GNUTLS_SAN_OTHERNAME) {
927 ret =
928 _gnutls_parse_general_name2(c2,
929 "authorityCertIssuer",
930 i,
931 &othername_oid,
932 NULL, 1);
933 if (ret < 0)
934 break;
935 }
936
937 ret = subject_alt_names_set(&aki->cert_issuer.names,
938 &aki->cert_issuer.size,
939 type, &san,
940 (char *)othername_oid.data, 1);
941 if (ret < 0)
942 break;
943 }
944
945 aki->cert_issuer.size = i;
946 if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
947 && ret != GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) {
948 gnutls_assert();
949 gnutls_free(san.data);
950 gnutls_free(othername_oid.data);
951 goto cleanup;
952 }
953
954 /* Read the serial number */
955 ret =
956 _gnutls_x509_read_value(c2, "authorityCertSerialNumber",
957 &aki->serial);
958 if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
959 && ret != GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) {
960 gnutls_assert();
961 goto cleanup;
962 }
963
964 /* Read the key identifier */
965 ret = _gnutls_x509_read_value(c2, "keyIdentifier", &aki->id);
966 if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
967 && ret != GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) {
968 gnutls_assert();
969 goto cleanup;
970 }
971
972 ret = 0;
973
974 cleanup:
975 asn1_delete_structure(&c2);
976
977 return ret;
978 }
979
980 /**
981 * gnutls_x509_ext_export_authority_key_id:
982 * @aki: An initialized authority key identifier
983 * @ext: The DER-encoded extension data; must be freed using gnutls_free().
984 *
985 * This function will convert the provided key identifier to a
986 * DER-encoded PKIX AuthorityKeyIdentifier extension.
987 * The output data in @ext will be allocated using
988 * gnutls_malloc().
989 *
990 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
991 *
992 * Since: 3.3.0
993 **/
gnutls_x509_ext_export_authority_key_id(gnutls_x509_aki_t aki,gnutls_datum_t * ext)994 int gnutls_x509_ext_export_authority_key_id(gnutls_x509_aki_t aki,
995 gnutls_datum_t * ext)
996 {
997 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
998 unsigned i;
999 int result, ret;
1000
1001 result =
1002 asn1_create_element(_gnutls_get_pkix(),
1003 "PKIX1.AuthorityKeyIdentifier", &c2);
1004 if (result != ASN1_SUCCESS) {
1005 gnutls_assert();
1006 return _gnutls_asn2err(result);
1007 }
1008
1009 if (aki->id.data != NULL) {
1010 result =
1011 asn1_write_value(c2, "keyIdentifier", aki->id.data,
1012 aki->id.size);
1013 if (result != ASN1_SUCCESS) {
1014 gnutls_assert();
1015 ret = _gnutls_asn2err(result);
1016 goto cleanup;
1017 }
1018 } else {
1019 (void)asn1_write_value(c2, "keyIdentifier", NULL, 0);
1020 }
1021
1022 if (aki->serial.data != NULL) {
1023 result =
1024 asn1_write_value(c2, "authorityCertSerialNumber",
1025 aki->serial.data, aki->serial.size);
1026 if (result != ASN1_SUCCESS) {
1027 gnutls_assert();
1028 ret = _gnutls_asn2err(result);
1029 goto cleanup;
1030 }
1031 } else {
1032 (void)asn1_write_value(c2, "authorityCertSerialNumber", NULL, 0);
1033 }
1034
1035 if (aki->cert_issuer.size == 0) {
1036 (void)asn1_write_value(c2, "authorityCertIssuer", NULL, 0);
1037 } else {
1038 for (i = 0; i < aki->cert_issuer.size; i++) {
1039 ret =
1040 _gnutls_write_new_general_name(c2,
1041 "authorityCertIssuer",
1042 aki->cert_issuer.
1043 names[i].type,
1044 aki->
1045 cert_issuer.names[i].
1046 san.data,
1047 aki->cert_issuer.
1048 names[i].san.size);
1049 if (ret < 0) {
1050 gnutls_assert();
1051 goto cleanup;
1052 }
1053 }
1054 }
1055
1056 ret = _gnutls_x509_der_encode(c2, "", ext, 0);
1057 if (ret < 0) {
1058 gnutls_assert();
1059 goto cleanup;
1060 }
1061
1062 ret = 0;
1063 cleanup:
1064 asn1_delete_structure(&c2);
1065 return ret;
1066
1067 }
1068
1069 /**
1070 * gnutls_x509_ext_import_key_usage:
1071 * @ext: the DER encoded extension data
1072 * @key_usage: where the key usage bits will be stored
1073 *
1074 * This function will return certificate's key usage, by reading the DER
1075 * data of the keyUsage X.509 extension (2.5.29.15). The key usage value will ORed
1076 * values of the: %GNUTLS_KEY_DIGITAL_SIGNATURE,
1077 * %GNUTLS_KEY_NON_REPUDIATION, %GNUTLS_KEY_KEY_ENCIPHERMENT,
1078 * %GNUTLS_KEY_DATA_ENCIPHERMENT, %GNUTLS_KEY_KEY_AGREEMENT,
1079 * %GNUTLS_KEY_KEY_CERT_SIGN, %GNUTLS_KEY_CRL_SIGN,
1080 * %GNUTLS_KEY_ENCIPHER_ONLY, %GNUTLS_KEY_DECIPHER_ONLY.
1081 *
1082 * Returns: the certificate key usage, or a negative error code in case of
1083 * parsing error. If the certificate does not contain the keyUsage
1084 * extension %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be
1085 * returned.
1086 *
1087 * Since: 3.3.0
1088 **/
gnutls_x509_ext_import_key_usage(const gnutls_datum_t * ext,unsigned int * key_usage)1089 int gnutls_x509_ext_import_key_usage(const gnutls_datum_t * ext,
1090 unsigned int *key_usage)
1091 {
1092 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
1093 int len, result;
1094 uint8_t str[2];
1095
1096 str[0] = str[1] = 0;
1097 *key_usage = 0;
1098
1099 if ((result = asn1_create_element
1100 (_gnutls_get_pkix(), "PKIX1.KeyUsage", &c2)) != ASN1_SUCCESS) {
1101 gnutls_assert();
1102 return _gnutls_asn2err(result);
1103 }
1104
1105 result = _asn1_strict_der_decode(&c2, ext->data, ext->size, NULL);
1106 if (result != ASN1_SUCCESS) {
1107 gnutls_assert();
1108 asn1_delete_structure(&c2);
1109 return _gnutls_asn2err(result);
1110 }
1111
1112 len = sizeof(str);
1113 result = asn1_read_value(c2, "", str, &len);
1114 if (result != ASN1_SUCCESS) {
1115 gnutls_assert();
1116 asn1_delete_structure(&c2);
1117 return 0;
1118 }
1119
1120 *key_usage = str[0] | (str[1] << 8);
1121
1122 asn1_delete_structure(&c2);
1123
1124 return 0;
1125 }
1126
1127 /**
1128 * gnutls_x509_ext_export_key_usage:
1129 * @usage: an ORed sequence of the GNUTLS_KEY_* elements.
1130 * @ext: The DER-encoded extension data; must be freed using gnutls_free().
1131 *
1132 * This function will convert the keyUsage bit string to a DER
1133 * encoded PKIX extension. The @ext data will be allocated using
1134 * gnutls_malloc().
1135 *
1136 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1137 * negative error value.
1138 *
1139 * Since: 3.3.0
1140 **/
gnutls_x509_ext_export_key_usage(unsigned int usage,gnutls_datum_t * ext)1141 int gnutls_x509_ext_export_key_usage(unsigned int usage, gnutls_datum_t * ext)
1142 {
1143 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
1144 int result;
1145 uint8_t str[2];
1146
1147 result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.KeyUsage", &c2);
1148 if (result != ASN1_SUCCESS) {
1149 gnutls_assert();
1150 return _gnutls_asn2err(result);
1151 }
1152
1153 str[0] = usage & 0xff;
1154 str[1] = usage >> 8;
1155
1156 /* Since KeyUsage is a BIT STRING, the input to asn1_write_value
1157 * is the number of bits to be read. */
1158 result = asn1_write_value(c2, "", str, 9);
1159 if (result != ASN1_SUCCESS) {
1160 gnutls_assert();
1161 asn1_delete_structure(&c2);
1162 return _gnutls_asn2err(result);
1163 }
1164
1165 result = _gnutls_x509_der_encode(c2, "", ext, 0);
1166
1167 asn1_delete_structure(&c2);
1168
1169 if (result < 0) {
1170 gnutls_assert();
1171 return result;
1172 }
1173
1174 return 0;
1175 }
1176
1177 /**
1178 * gnutls_x509_ext_import_inhibit_anypolicy:
1179 * @ext: the DER encoded extension data
1180 * @skipcerts: will hold the number of certificates after which anypolicy is no longer acceptable.
1181 *
1182 * This function will return certificate's value of SkipCerts,
1183 * by reading the DER data of the Inhibit anyPolicy X.509 extension (2.5.29.54).
1184 *
1185 * The @skipcerts value is the number of additional certificates that
1186 * may appear in the path before the anyPolicy (%GNUTLS_X509_OID_POLICY_ANY)
1187 * is no longer acceptable.
1188 *
1189 * Returns: zero, or a negative error code in case of
1190 * parsing error. If the certificate does not contain the Inhibit anyPolicy
1191 * extension %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be
1192 * returned.
1193 *
1194 * Since: 3.6.0
1195 **/
gnutls_x509_ext_import_inhibit_anypolicy(const gnutls_datum_t * ext,unsigned int * skipcerts)1196 int gnutls_x509_ext_import_inhibit_anypolicy(const gnutls_datum_t * ext,
1197 unsigned int *skipcerts)
1198 {
1199 int ret;
1200
1201 ret = _gnutls_x509_read_der_uint(ext->data, ext->size, skipcerts);
1202 if (ret < 0) {
1203 gnutls_assert();
1204 }
1205
1206 return ret;
1207 }
1208
1209 /**
1210 * gnutls_x509_ext_export_inhibit_anypolicy:
1211 * @skipcerts: number of certificates after which anypolicy is no longer acceptable.
1212 * @ext: The DER-encoded extension data; must be freed using gnutls_free().
1213 *
1214 * This function will convert the @skipcerts value to a DER
1215 * encoded Inhibit AnyPolicy PKIX extension. The @ext data will be allocated using
1216 * gnutls_malloc().
1217 *
1218 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1219 * negative error value.
1220 *
1221 * Since: 3.6.0
1222 **/
gnutls_x509_ext_export_inhibit_anypolicy(unsigned int skipcerts,gnutls_datum_t * ext)1223 int gnutls_x509_ext_export_inhibit_anypolicy(unsigned int skipcerts, gnutls_datum_t * ext)
1224 {
1225 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
1226 int result, ret;
1227
1228 result = asn1_create_element(_gnutls_get_gnutls_asn(), "GNUTLS.DSAPublicKey", &c2);
1229 if (result != ASN1_SUCCESS) {
1230 gnutls_assert();
1231 return _gnutls_asn2err(result);
1232 }
1233
1234 ret = _gnutls_x509_write_uint32(c2, "", skipcerts);
1235 if (ret < 0) {
1236 gnutls_assert();
1237 goto cleanup;
1238 }
1239
1240 ret = _gnutls_x509_der_encode(c2, "", ext, 0);
1241 if (ret < 0) {
1242 gnutls_assert();
1243 goto cleanup;
1244 }
1245
1246 ret = 0;
1247
1248 cleanup:
1249 asn1_delete_structure(&c2);
1250
1251 return ret;
1252 }
1253
1254 /**
1255 * gnutls_x509_ext_import_private_key_usage_period:
1256 * @ext: the DER encoded extension data
1257 * @activation: Will hold the activation time
1258 * @expiration: Will hold the expiration time
1259 *
1260 * This function will return the expiration and activation
1261 * times of the private key as written in the
1262 * PKIX extension 2.5.29.16.
1263 *
1264 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1265 * negative error value.
1266 *
1267 * Since: 3.3.0
1268 **/
gnutls_x509_ext_import_private_key_usage_period(const gnutls_datum_t * ext,time_t * activation,time_t * expiration)1269 int gnutls_x509_ext_import_private_key_usage_period(const gnutls_datum_t * ext,
1270 time_t * activation,
1271 time_t * expiration)
1272 {
1273 int result, ret;
1274 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
1275
1276 result = asn1_create_element
1277 (_gnutls_get_pkix(), "PKIX1.PrivateKeyUsagePeriod", &c2);
1278 if (result != ASN1_SUCCESS) {
1279 gnutls_assert();
1280 ret = _gnutls_asn2err(result);
1281 goto cleanup;
1282 }
1283
1284 result = _asn1_strict_der_decode(&c2, ext->data, ext->size, NULL);
1285 if (result != ASN1_SUCCESS) {
1286 gnutls_assert();
1287 ret = _gnutls_asn2err(result);
1288 goto cleanup;
1289 }
1290
1291 if (activation)
1292 *activation = _gnutls_x509_get_time(c2, "notBefore", 1);
1293
1294 if (expiration)
1295 *expiration = _gnutls_x509_get_time(c2, "notAfter", 1);
1296
1297 ret = 0;
1298
1299 cleanup:
1300 asn1_delete_structure(&c2);
1301
1302 return ret;
1303 }
1304
1305 /**
1306 * gnutls_x509_ext_export_private_key_usage_period:
1307 * @activation: The activation time
1308 * @expiration: The expiration time
1309 * @ext: The DER-encoded extension data; must be freed using gnutls_free().
1310 *
1311 * This function will convert the periods provided to a private key
1312 * usage DER encoded extension (2.5.29.16).
1313 (
1314 * The @ext data will be allocated using
1315 * gnutls_malloc().
1316 *
1317 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1318 * negative error value.
1319 *
1320 * Since: 3.3.0
1321 **/
gnutls_x509_ext_export_private_key_usage_period(time_t activation,time_t expiration,gnutls_datum_t * ext)1322 int gnutls_x509_ext_export_private_key_usage_period(time_t activation,
1323 time_t expiration,
1324 gnutls_datum_t * ext)
1325 {
1326 int result;
1327 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
1328
1329 result =
1330 asn1_create_element(_gnutls_get_pkix(),
1331 "PKIX1.PrivateKeyUsagePeriod", &c2);
1332 if (result != ASN1_SUCCESS) {
1333 gnutls_assert();
1334 return _gnutls_asn2err(result);
1335 }
1336
1337 result = _gnutls_x509_set_time(c2, "notBefore", activation, 1);
1338 if (result < 0) {
1339 gnutls_assert();
1340 goto cleanup;
1341 }
1342
1343 result = _gnutls_x509_set_time(c2, "notAfter", expiration, 1);
1344 if (result < 0) {
1345 gnutls_assert();
1346 goto cleanup;
1347 }
1348
1349 result = _gnutls_x509_der_encode(c2, "", ext, 0);
1350 if (result < 0) {
1351 gnutls_assert();
1352 goto cleanup;
1353 }
1354
1355 cleanup:
1356 asn1_delete_structure(&c2);
1357
1358 return result;
1359
1360 }
1361
1362 /**
1363 * gnutls_x509_ext_import_basic_constraints:
1364 * @ext: the DER encoded extension data
1365 * @ca: will be non zero if the CA status is true
1366 * @pathlen: the path length constraint; will be set to -1 for no limit
1367 *
1368 * This function will return the CA status and path length constraint
1369 * as written in the PKIX extension 2.5.29.19.
1370 *
1371 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1372 * negative error value.
1373 *
1374 * Since: 3.3.0
1375 **/
gnutls_x509_ext_import_basic_constraints(const gnutls_datum_t * ext,unsigned int * ca,int * pathlen)1376 int gnutls_x509_ext_import_basic_constraints(const gnutls_datum_t * ext,
1377 unsigned int *ca, int *pathlen)
1378 {
1379 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
1380 char str[128]="";
1381 int len, result;
1382
1383 if ((result = asn1_create_element
1384 (_gnutls_get_pkix(), "PKIX1.BasicConstraints",
1385 &c2)) != ASN1_SUCCESS) {
1386 gnutls_assert();
1387 return _gnutls_asn2err(result);
1388 }
1389
1390 result = _asn1_strict_der_decode(&c2, ext->data, ext->size, NULL);
1391 if (result != ASN1_SUCCESS) {
1392 gnutls_assert();
1393 result = _gnutls_asn2err(result);
1394 goto cleanup;
1395 }
1396
1397 if (pathlen) {
1398 result = _gnutls_x509_read_uint(c2, "pathLenConstraint",
1399 (unsigned int *)
1400 pathlen);
1401 if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
1402 *pathlen = -1;
1403 else if (result != GNUTLS_E_SUCCESS) {
1404 gnutls_assert();
1405 result = _gnutls_asn2err(result);
1406 goto cleanup;
1407 }
1408 }
1409
1410 /* the default value of cA is false.
1411 */
1412 len = sizeof(str) - 1;
1413 result = asn1_read_value(c2, "cA", str, &len);
1414 if (result == ASN1_SUCCESS && strcmp(str, "TRUE") == 0)
1415 *ca = 1;
1416 else
1417 *ca = 0;
1418
1419 result = 0;
1420 cleanup:
1421 asn1_delete_structure(&c2);
1422
1423 return result;
1424
1425 }
1426
1427 /**
1428 * gnutls_x509_ext_export_basic_constraints:
1429 * @ca: non-zero for a CA
1430 * @pathlen: The path length constraint (set to -1 for no constraint)
1431 * @ext: The DER-encoded extension data; must be freed using gnutls_free().
1432 *
1433 * This function will convert the parameters provided to a basic constraints
1434 * DER encoded extension (2.5.29.19).
1435 (
1436 * The @ext data will be allocated using
1437 * gnutls_malloc().
1438 *
1439 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1440 * negative error value.
1441 *
1442 * Since: 3.3.0
1443 **/
gnutls_x509_ext_export_basic_constraints(unsigned int ca,int pathlen,gnutls_datum_t * ext)1444 int gnutls_x509_ext_export_basic_constraints(unsigned int ca, int pathlen,
1445 gnutls_datum_t * ext)
1446 {
1447 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
1448 const char *str;
1449 int result;
1450
1451 if (ca == 0)
1452 str = "FALSE";
1453 else
1454 str = "TRUE";
1455
1456 result =
1457 asn1_create_element(_gnutls_get_pkix(),
1458 "PKIX1.BasicConstraints", &c2);
1459 if (result != ASN1_SUCCESS) {
1460 gnutls_assert();
1461 result = _gnutls_asn2err(result);
1462 goto cleanup;
1463 }
1464
1465 result = asn1_write_value(c2, "cA", str, 1);
1466 if (result != ASN1_SUCCESS) {
1467 gnutls_assert();
1468 result = _gnutls_asn2err(result);
1469 goto cleanup;
1470 }
1471
1472 if (pathlen < 0) {
1473 result = asn1_write_value(c2, "pathLenConstraint", NULL, 0);
1474 if (result < 0)
1475 result = _gnutls_asn2err(result);
1476 } else
1477 result =
1478 _gnutls_x509_write_uint32(c2, "pathLenConstraint", pathlen);
1479 if (result < 0) {
1480 gnutls_assert();
1481 goto cleanup;
1482 }
1483
1484 result = _gnutls_x509_der_encode(c2, "", ext, 0);
1485 if (result < 0) {
1486 gnutls_assert();
1487 goto cleanup;
1488 }
1489
1490 result = 0;
1491
1492 cleanup:
1493 asn1_delete_structure(&c2);
1494 return result;
1495
1496 }
1497
1498 /**
1499 * gnutls_x509_ext_import_proxy:
1500 * @ext: the DER encoded extension data
1501 * @pathlen: pointer to output integer indicating path length (may be
1502 * NULL), non-negative error codes indicate a present pCPathLenConstraint
1503 * field and the actual value, -1 indicate that the field is absent.
1504 * @policyLanguage: output variable with OID of policy language
1505 * @policy: output variable with policy data
1506 * @sizeof_policy: output variable with size of policy data
1507 *
1508 * This function will return the information from a proxy certificate
1509 * extension. It reads the ProxyCertInfo X.509 extension (1.3.6.1.5.5.7.1.14).
1510 * The @policyLanguage and @policy values must be deinitialized using gnutls_free() after use.
1511 *
1512 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1513 * negative error value.
1514 *
1515 * Since: 3.3.0
1516 **/
gnutls_x509_ext_import_proxy(const gnutls_datum_t * ext,int * pathlen,char ** policyLanguage,char ** policy,size_t * sizeof_policy)1517 int gnutls_x509_ext_import_proxy(const gnutls_datum_t *ext, int *pathlen,
1518 char **policyLanguage, char **policy,
1519 size_t *sizeof_policy)
1520 {
1521 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
1522 int result;
1523 gnutls_datum_t value1 = { NULL, 0 };
1524 gnutls_datum_t value2 = { NULL, 0 };
1525
1526 if ((result = asn1_create_element
1527 (_gnutls_get_pkix(), "PKIX1.ProxyCertInfo",
1528 &c2)) != ASN1_SUCCESS) {
1529 gnutls_assert();
1530 return _gnutls_asn2err(result);
1531 }
1532
1533 result = _asn1_strict_der_decode(&c2, ext->data, ext->size, NULL);
1534 if (result != ASN1_SUCCESS) {
1535 gnutls_assert();
1536 result = _gnutls_asn2err(result);
1537 goto cleanup;
1538 }
1539
1540 if (pathlen) {
1541 result = _gnutls_x509_read_uint(c2, "pCPathLenConstraint",
1542 (unsigned int *)
1543 pathlen);
1544 if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
1545 *pathlen = -1;
1546 else if (result != GNUTLS_E_SUCCESS) {
1547 gnutls_assert();
1548 result = _gnutls_asn2err(result);
1549 goto cleanup;
1550 }
1551 }
1552
1553 result = _gnutls_x509_read_value(c2, "proxyPolicy.policyLanguage",
1554 &value1);
1555 if (result < 0) {
1556 gnutls_assert();
1557 goto cleanup;
1558 }
1559
1560 result = _gnutls_x509_read_value(c2, "proxyPolicy.policy", &value2);
1561 if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) {
1562 if (policy)
1563 *policy = NULL;
1564 if (sizeof_policy)
1565 *sizeof_policy = 0;
1566 } else if (result < 0) {
1567 gnutls_assert();
1568 goto cleanup;
1569 } else {
1570 if (policy) {
1571 *policy = (char *)value2.data;
1572 value2.data = NULL;
1573 }
1574 if (sizeof_policy)
1575 *sizeof_policy = value2.size;
1576 }
1577
1578 if (policyLanguage) {
1579 *policyLanguage = (char *)value1.data;
1580 value1.data = NULL;
1581 }
1582
1583 result = 0;
1584 cleanup:
1585 gnutls_free(value1.data);
1586 gnutls_free(value2.data);
1587 asn1_delete_structure(&c2);
1588
1589 return result;
1590 }
1591
1592 /**
1593 * gnutls_x509_ext_export_proxy:
1594 * @pathLenConstraint: A negative value will remove the path length constraint,
1595 * while non-negative values will be set as the length of the pathLenConstraints field.
1596 * @policyLanguage: OID describing the language of @policy.
1597 * @policy: uint8_t byte array with policy language, can be %NULL
1598 * @sizeof_policy: size of @policy.
1599 * @ext: The DER-encoded extension data; must be freed using gnutls_free().
1600 *
1601 * This function will convert the parameters provided to a proxyCertInfo extension.
1602 *
1603 * The @ext data will be allocated using gnutls_malloc().
1604 *
1605 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1606 * negative error value.
1607 *
1608 * Since: 3.3.0
1609 **/
gnutls_x509_ext_export_proxy(int pathLenConstraint,const char * policyLanguage,const char * policy,size_t sizeof_policy,gnutls_datum_t * ext)1610 int gnutls_x509_ext_export_proxy(int pathLenConstraint, const char *policyLanguage,
1611 const char *policy, size_t sizeof_policy,
1612 gnutls_datum_t * ext)
1613 {
1614 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
1615 int result;
1616
1617 result = asn1_create_element(_gnutls_get_pkix(),
1618 "PKIX1.ProxyCertInfo", &c2);
1619 if (result != ASN1_SUCCESS) {
1620 gnutls_assert();
1621 return _gnutls_asn2err(result);
1622 }
1623
1624 if (pathLenConstraint < 0) {
1625 result = asn1_write_value(c2, "pCPathLenConstraint", NULL, 0);
1626 if (result != ASN1_SUCCESS) {
1627 gnutls_assert();
1628 result = _gnutls_asn2err(result);
1629 goto cleanup;
1630 }
1631 } else {
1632 result =
1633 _gnutls_x509_write_uint32(c2, "pCPathLenConstraint",
1634 pathLenConstraint);
1635
1636 if (result < 0) {
1637 gnutls_assert();
1638 goto cleanup;
1639 }
1640 }
1641
1642 result = asn1_write_value(c2, "proxyPolicy.policyLanguage",
1643 policyLanguage, 1);
1644 if (result < 0) {
1645 gnutls_assert();
1646 result = _gnutls_asn2err(result);
1647 goto cleanup;
1648 }
1649
1650 result = asn1_write_value(c2, "proxyPolicy.policy",
1651 policy, sizeof_policy);
1652 if (result < 0) {
1653 gnutls_assert();
1654 result = _gnutls_asn2err(result);
1655 goto cleanup;
1656 }
1657
1658 result = _gnutls_x509_der_encode(c2, "", ext, 0);
1659 if (result < 0) {
1660 gnutls_assert();
1661 goto cleanup;
1662 }
1663
1664 result = 0;
1665 cleanup:
1666 asn1_delete_structure(&c2);
1667 return result;
1668
1669 }
1670
decode_user_notice(const void * data,size_t size,gnutls_datum_t * txt)1671 static int decode_user_notice(const void *data, size_t size,
1672 gnutls_datum_t * txt)
1673 {
1674 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
1675 int ret, len;
1676 char choice_type[64];
1677 char name[128];
1678 gnutls_datum_t td = {NULL,0}, utd;
1679
1680 ret = asn1_create_element(_gnutls_get_pkix(), "PKIX1.UserNotice", &c2);
1681 if (ret != ASN1_SUCCESS) {
1682 gnutls_assert();
1683 ret = GNUTLS_E_PARSING_ERROR;
1684 goto cleanup;
1685 }
1686
1687 ret = _asn1_strict_der_decode(&c2, data, size, NULL);
1688 if (ret != ASN1_SUCCESS) {
1689 gnutls_assert();
1690 ret = GNUTLS_E_PARSING_ERROR;
1691 goto cleanup;
1692 }
1693
1694 len = sizeof(choice_type);
1695 ret = asn1_read_value(c2, "explicitText", choice_type, &len);
1696 if (ret != ASN1_SUCCESS) {
1697 gnutls_assert();
1698 ret = GNUTLS_E_PARSING_ERROR;
1699 goto cleanup;
1700 }
1701
1702 if (strcmp(choice_type, "utf8String") != 0
1703 && strcmp(choice_type, "ia5String") != 0
1704 && strcmp(choice_type, "bmpString") != 0
1705 && strcmp(choice_type, "visibleString") != 0) {
1706 gnutls_assert();
1707 ret = GNUTLS_E_PARSING_ERROR;
1708 goto cleanup;
1709 }
1710
1711 snprintf(name, sizeof(name), "explicitText.%s", choice_type);
1712
1713 ret = _gnutls_x509_read_value(c2, name, &td);
1714 if (ret < 0) {
1715 gnutls_assert();
1716 goto cleanup;
1717 }
1718
1719 if (strcmp(choice_type, "bmpString") == 0) { /* convert to UTF-8 */
1720 ret = _gnutls_ucs2_to_utf8(td.data, td.size, &utd, 1);
1721 _gnutls_free_datum(&td);
1722 if (ret < 0) {
1723 gnutls_assert();
1724 goto cleanup;
1725 }
1726
1727 td.data = utd.data;
1728 td.size = utd.size;
1729 } else {
1730 /* _gnutls_x509_read_value allows that */
1731 td.data[td.size] = 0;
1732 }
1733
1734 txt->data = (void *)td.data;
1735 txt->size = td.size;
1736 ret = 0;
1737
1738 cleanup:
1739 asn1_delete_structure(&c2);
1740 return ret;
1741
1742 }
1743
1744 struct gnutls_x509_policies_st {
1745 struct gnutls_x509_policy_st policy[MAX_ENTRIES];
1746 unsigned int size;
1747 };
1748
1749 /**
1750 * gnutls_x509_policies_init:
1751 * @policies: The authority key ID
1752 *
1753 * This function will initialize an authority key ID type.
1754 *
1755 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
1756 *
1757 * Since: 3.3.0
1758 **/
gnutls_x509_policies_init(gnutls_x509_policies_t * policies)1759 int gnutls_x509_policies_init(gnutls_x509_policies_t * policies)
1760 {
1761 *policies = gnutls_calloc(1, sizeof(struct gnutls_x509_policies_st));
1762 if (*policies == NULL)
1763 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1764
1765 return 0;
1766 }
1767
1768 /**
1769 * gnutls_x509_policies_deinit:
1770 * @policies: The authority key identifier
1771 *
1772 * This function will deinitialize an authority key identifier type.
1773 *
1774 * Since: 3.3.0
1775 **/
gnutls_x509_policies_deinit(gnutls_x509_policies_t policies)1776 void gnutls_x509_policies_deinit(gnutls_x509_policies_t policies)
1777 {
1778 unsigned i;
1779
1780 for (i = 0; i < policies->size; i++) {
1781 gnutls_x509_policy_release(&policies->policy[i]);
1782 }
1783 gnutls_free(policies);
1784 }
1785
1786 /**
1787 * gnutls_x509_policies_get:
1788 * @policies: The policies
1789 * @seq: The index of the name to get
1790 * @policy: Will hold the policy
1791 *
1792 * This function will return a specific policy as stored in
1793 * the @policies type. The returned values should be treated as constant
1794 * and valid for the lifetime of @policies.
1795 *
1796 * The any policy OID is available as the %GNUTLS_X509_OID_POLICY_ANY macro.
1797 *
1798 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
1799 * if the index is out of bounds, otherwise a negative error value.
1800 *
1801 * Since: 3.3.0
1802 **/
gnutls_x509_policies_get(gnutls_x509_policies_t policies,unsigned int seq,struct gnutls_x509_policy_st * policy)1803 int gnutls_x509_policies_get(gnutls_x509_policies_t policies,
1804 unsigned int seq,
1805 struct gnutls_x509_policy_st *policy)
1806 {
1807 if (seq >= policies->size)
1808 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1809
1810 if (policy) {
1811 memcpy(policy, &policies->policy[seq],
1812 sizeof(struct gnutls_x509_policy_st));
1813 }
1814
1815 return 0;
1816 }
1817
_gnutls_x509_policies_erase(gnutls_x509_policies_t policies,unsigned int seq)1818 void _gnutls_x509_policies_erase(gnutls_x509_policies_t policies,
1819 unsigned int seq)
1820 {
1821 if (seq >= policies->size)
1822 return;
1823
1824 memset(&policies->policy[seq], 0, sizeof(struct gnutls_x509_policy_st));
1825 }
1826
1827 /**
1828 * gnutls_x509_policies_set:
1829 * @policies: An initialized policies
1830 * @seq: The index of the name to get
1831 * @policy: Contains the policy to set
1832 *
1833 * This function will store the specified policy in
1834 * the provided @policies.
1835 *
1836 * Returns: On success, %GNUTLS_E_SUCCESS (0), otherwise a negative error value.
1837 *
1838 * Since: 3.3.0
1839 **/
gnutls_x509_policies_set(gnutls_x509_policies_t policies,const struct gnutls_x509_policy_st * policy)1840 int gnutls_x509_policies_set(gnutls_x509_policies_t policies,
1841 const struct gnutls_x509_policy_st *policy)
1842 {
1843 unsigned i;
1844
1845 if (policies->size + 1 > MAX_ENTRIES)
1846 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1847
1848 policies->policy[policies->size].oid = gnutls_strdup(policy->oid);
1849 if (policies->policy[policies->size].oid == NULL)
1850 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1851
1852 for (i = 0; i < policy->qualifiers; i++) {
1853 policies->policy[policies->size].qualifier[i].type =
1854 policy->qualifier[i].type;
1855 policies->policy[policies->size].qualifier[i].size =
1856 policy->qualifier[i].size;
1857 policies->policy[policies->size].qualifier[i].data =
1858 gnutls_malloc(policy->qualifier[i].size + 1);
1859 if (policies->policy[policies->size].qualifier[i].data == NULL)
1860 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1861 memcpy(policies->policy[policies->size].qualifier[i].data,
1862 policy->qualifier[i].data, policy->qualifier[i].size);
1863 policies->policy[policies->size].qualifier[i].data[policy->
1864 qualifier[i].
1865 size] = 0;
1866 }
1867
1868 policies->policy[policies->size].qualifiers = policy->qualifiers;
1869 policies->size++;
1870
1871 return 0;
1872 }
1873
1874 /**
1875 * gnutls_x509_ext_import_policies:
1876 * @ext: the DER encoded extension data
1877 * @policies: A pointer to an initialized policies.
1878 * @flags: should be zero
1879 *
1880 * This function will extract the certificate policy extension (2.5.29.32)
1881 * and store it the provided policies.
1882 *
1883 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
1884 *
1885 * Since: 3.3.0
1886 **/
gnutls_x509_ext_import_policies(const gnutls_datum_t * ext,gnutls_x509_policies_t policies,unsigned int flags)1887 int gnutls_x509_ext_import_policies(const gnutls_datum_t * ext,
1888 gnutls_x509_policies_t policies,
1889 unsigned int flags)
1890 {
1891 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
1892 char tmpstr[128];
1893 char tmpoid[MAX_OID_SIZE];
1894 gnutls_datum_t tmpd = { NULL, 0 };
1895 int ret, len;
1896 unsigned i, j, current = 0;
1897
1898 ret = asn1_create_element
1899 (_gnutls_get_pkix(), "PKIX1.certificatePolicies", &c2);
1900 if (ret != ASN1_SUCCESS) {
1901 gnutls_assert();
1902 ret = _gnutls_asn2err(ret);
1903 goto cleanup;
1904 }
1905
1906 ret = _asn1_strict_der_decode(&c2, ext->data, ext->size, NULL);
1907 if (ret != ASN1_SUCCESS) {
1908 gnutls_assert();
1909 ret = _gnutls_asn2err(ret);
1910 goto cleanup;
1911 }
1912
1913 for (j = 0;; j++) {
1914 if (j >= MAX_ENTRIES)
1915 break;
1916
1917 memset(&policies->policy[j], 0,
1918 sizeof(struct gnutls_x509_policy_st));
1919
1920 /* create a string like "?1"
1921 */
1922 snprintf(tmpstr, sizeof(tmpstr), "?%u.policyIdentifier", j + 1);
1923 current = j+1;
1924
1925 ret = _gnutls_x509_read_value(c2, tmpstr, &tmpd);
1926 if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
1927 break;
1928
1929 if (ret < 0) {
1930 gnutls_assert();
1931 goto full_cleanup;
1932 }
1933
1934 policies->policy[j].oid = (void *)tmpd.data;
1935 tmpd.data = NULL;
1936
1937 for (i = 0; i < GNUTLS_MAX_QUALIFIERS; i++) {
1938 gnutls_datum_t td;
1939
1940 snprintf(tmpstr, sizeof(tmpstr),
1941 "?%u.policyQualifiers.?%u.policyQualifierId",
1942 j + 1, i + 1);
1943
1944 len = sizeof(tmpoid);
1945 ret = asn1_read_value(c2, tmpstr, tmpoid, &len);
1946
1947 if (ret == ASN1_ELEMENT_NOT_FOUND)
1948 break; /* finished */
1949
1950 if (ret != ASN1_SUCCESS) {
1951 gnutls_assert();
1952 ret = _gnutls_asn2err(ret);
1953 goto full_cleanup;
1954 }
1955
1956 if (strcmp(tmpoid, "1.3.6.1.5.5.7.2.1") == 0) {
1957 snprintf(tmpstr, sizeof(tmpstr),
1958 "?%u.policyQualifiers.?%u.qualifier",
1959 j + 1, i + 1);
1960
1961 ret =
1962 _gnutls_x509_read_string(c2, tmpstr, &td,
1963 ASN1_ETYPE_IA5_STRING, 0);
1964 if (ret < 0) {
1965 gnutls_assert();
1966 goto full_cleanup;
1967 }
1968
1969 policies->policy[j].qualifier[i].data =
1970 (void *)td.data;
1971 policies->policy[j].qualifier[i].size = td.size;
1972 td.data = NULL;
1973 policies->policy[j].qualifier[i].type =
1974 GNUTLS_X509_QUALIFIER_URI;
1975 } else if (strcmp(tmpoid, "1.3.6.1.5.5.7.2.2") == 0) {
1976 gnutls_datum_t txt = {NULL, 0};
1977
1978 snprintf(tmpstr, sizeof(tmpstr),
1979 "?%u.policyQualifiers.?%u.qualifier",
1980 j + 1, i + 1);
1981
1982 ret = _gnutls_x509_read_value(c2, tmpstr, &td);
1983 if (ret < 0) {
1984 gnutls_assert();
1985 goto full_cleanup;
1986 }
1987
1988 ret =
1989 decode_user_notice(td.data, td.size, &txt);
1990 gnutls_free(td.data);
1991
1992 if (ret < 0) {
1993 gnutls_assert();
1994 goto full_cleanup;
1995 }
1996
1997 policies->policy[j].qualifier[i].data =
1998 (void *)txt.data;
1999 policies->policy[j].qualifier[i].size =
2000 txt.size;
2001 policies->policy[j].qualifier[i].type =
2002 GNUTLS_X509_QUALIFIER_NOTICE;
2003 } else
2004 policies->policy[j].qualifier[i].type =
2005 GNUTLS_X509_QUALIFIER_UNKNOWN;
2006
2007 policies->policy[j].qualifiers++;
2008 }
2009
2010 }
2011
2012 policies->size = j;
2013
2014 ret = 0;
2015 goto cleanup;
2016
2017 full_cleanup:
2018 for (j = 0; j < current; j++)
2019 gnutls_x509_policy_release(&policies->policy[j]);
2020
2021 cleanup:
2022 _gnutls_free_datum(&tmpd);
2023 asn1_delete_structure(&c2);
2024 return ret;
2025
2026 }
2027
encode_user_notice(const gnutls_datum_t * txt,gnutls_datum_t * der_data)2028 static int encode_user_notice(const gnutls_datum_t * txt,
2029 gnutls_datum_t * der_data)
2030 {
2031 int result;
2032 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
2033
2034 if ((result =
2035 asn1_create_element(_gnutls_get_pkix(),
2036 "PKIX1.UserNotice", &c2)) != ASN1_SUCCESS) {
2037 gnutls_assert();
2038 result = _gnutls_asn2err(result);
2039 goto error;
2040 }
2041
2042 /* delete noticeRef */
2043 result = asn1_write_value(c2, "noticeRef", NULL, 0);
2044 if (result != ASN1_SUCCESS) {
2045 gnutls_assert();
2046 result = _gnutls_asn2err(result);
2047 goto error;
2048 }
2049
2050 result = asn1_write_value(c2, "explicitText", "utf8String", 1);
2051 if (result != ASN1_SUCCESS) {
2052 gnutls_assert();
2053 result = _gnutls_asn2err(result);
2054 goto error;
2055 }
2056
2057 result =
2058 asn1_write_value(c2, "explicitText.utf8String", txt->data,
2059 txt->size);
2060 if (result != ASN1_SUCCESS) {
2061 gnutls_assert();
2062 result = _gnutls_asn2err(result);
2063 goto error;
2064 }
2065
2066 result = _gnutls_x509_der_encode(c2, "", der_data, 0);
2067 if (result < 0) {
2068 gnutls_assert();
2069 goto error;
2070 }
2071
2072 result = 0;
2073
2074 error:
2075 asn1_delete_structure(&c2);
2076 return result;
2077
2078 }
2079
2080 /**
2081 * gnutls_x509_ext_export_policies:
2082 * @policies: A pointer to an initialized policies.
2083 * @ext: The DER-encoded extension data; must be freed using gnutls_free().
2084 *
2085 * This function will convert the provided policies, to a certificate policy
2086 * DER encoded extension (2.5.29.32).
2087 *
2088 * The @ext data will be allocated using gnutls_malloc().
2089 *
2090 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
2091 *
2092 * Since: 3.3.0
2093 **/
gnutls_x509_ext_export_policies(gnutls_x509_policies_t policies,gnutls_datum_t * ext)2094 int gnutls_x509_ext_export_policies(gnutls_x509_policies_t policies,
2095 gnutls_datum_t * ext)
2096 {
2097 int result;
2098 unsigned i, j;
2099 gnutls_datum_t der_data = {NULL, 0}, tmpd;
2100 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
2101 const char *oid;
2102
2103 result =
2104 asn1_create_element(_gnutls_get_pkix(),
2105 "PKIX1.certificatePolicies", &c2);
2106 if (result != ASN1_SUCCESS) {
2107 gnutls_assert();
2108 result = _gnutls_asn2err(result);
2109 goto cleanup;
2110 }
2111
2112 for (j = 0; j < policies->size; j++) {
2113 /* 1. write a new policy */
2114 result = asn1_write_value(c2, "", "NEW", 1);
2115 if (result != ASN1_SUCCESS) {
2116 gnutls_assert();
2117 result = _gnutls_asn2err(result);
2118 goto cleanup;
2119 }
2120
2121 /* 2. Add the OID.
2122 */
2123 result =
2124 asn1_write_value(c2, "?LAST.policyIdentifier",
2125 policies->policy[j].oid, 1);
2126 if (result != ASN1_SUCCESS) {
2127 gnutls_assert();
2128 result = _gnutls_asn2err(result);
2129 goto cleanup;
2130 }
2131
2132 for (i = 0;
2133 i < MIN(policies->policy[j].qualifiers,
2134 GNUTLS_MAX_QUALIFIERS); i++) {
2135 result =
2136 asn1_write_value(c2, "?LAST.policyQualifiers",
2137 "NEW", 1);
2138 if (result != ASN1_SUCCESS) {
2139 gnutls_assert();
2140 result = _gnutls_asn2err(result);
2141 goto cleanup;
2142 }
2143
2144 if (policies->policy[j].qualifier[i].type ==
2145 GNUTLS_X509_QUALIFIER_URI)
2146 oid = "1.3.6.1.5.5.7.2.1";
2147 else if (policies->policy[j].qualifier[i].type ==
2148 GNUTLS_X509_QUALIFIER_NOTICE)
2149 oid = "1.3.6.1.5.5.7.2.2";
2150 else {
2151 result =
2152 gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
2153 goto cleanup;
2154 }
2155
2156 result =
2157 asn1_write_value(c2,
2158 "?LAST.policyQualifiers.?LAST.policyQualifierId",
2159 oid, 1);
2160 if (result != ASN1_SUCCESS) {
2161 gnutls_assert();
2162 result = _gnutls_asn2err(result);
2163 goto cleanup;
2164 }
2165
2166 if (policies->policy[j].qualifier[i].type ==
2167 GNUTLS_X509_QUALIFIER_URI) {
2168 tmpd.data =
2169 (void *)policies->policy[j].qualifier[i].
2170 data;
2171 tmpd.size =
2172 policies->policy[j].qualifier[i].size;
2173 result =
2174 _gnutls_x509_write_string(c2,
2175 "?LAST.policyQualifiers.?LAST.qualifier",
2176 &tmpd,
2177 ASN1_ETYPE_IA5_STRING);
2178 if (result < 0) {
2179 gnutls_assert();
2180 goto cleanup;
2181 }
2182 } else if (policies->policy[j].qualifier[i].type ==
2183 GNUTLS_X509_QUALIFIER_NOTICE) {
2184 tmpd.data =
2185 (void *)policies->policy[j].qualifier[i].
2186 data;
2187 tmpd.size =
2188 policies->policy[j].qualifier[i].size;
2189
2190 if (tmpd.size > 200) {
2191 gnutls_assert();
2192 result = GNUTLS_E_INVALID_REQUEST;
2193 goto cleanup;
2194 }
2195
2196 result = encode_user_notice(&tmpd, &der_data);
2197 if (result < 0) {
2198 gnutls_assert();
2199 goto cleanup;
2200 }
2201
2202 result =
2203 _gnutls_x509_write_value(c2,
2204 "?LAST.policyQualifiers.?LAST.qualifier",
2205 &der_data);
2206 _gnutls_free_datum(&der_data);
2207 if (result < 0) {
2208 gnutls_assert();
2209 goto cleanup;
2210 }
2211 }
2212 }
2213 }
2214
2215 result = _gnutls_x509_der_encode(c2, "", ext, 0);
2216 if (result < 0) {
2217 gnutls_assert();
2218 goto cleanup;
2219 }
2220
2221 cleanup:
2222 asn1_delete_structure(&c2);
2223
2224 return result;
2225 }
2226
2227 struct crl_dist_point_st {
2228 unsigned int type;
2229 gnutls_datum_t san;
2230 unsigned int reasons;
2231 };
2232
2233 struct gnutls_x509_crl_dist_points_st {
2234 struct crl_dist_point_st *points;
2235 unsigned int size;
2236 };
2237
2238 /**
2239 * gnutls_x509_crl_dist_points_init:
2240 * @cdp: The CRL distribution points
2241 *
2242 * This function will initialize a CRL distribution points type.
2243 *
2244 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
2245 *
2246 * Since: 3.3.0
2247 **/
gnutls_x509_crl_dist_points_init(gnutls_x509_crl_dist_points_t * cdp)2248 int gnutls_x509_crl_dist_points_init(gnutls_x509_crl_dist_points_t * cdp)
2249 {
2250 *cdp = gnutls_calloc(1, sizeof(struct gnutls_x509_crl_dist_points_st));
2251 if (*cdp == NULL)
2252 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2253
2254 return 0;
2255 }
2256
2257 /**
2258 * gnutls_x509_crl_dist_points_deinit:
2259 * @cdp: The CRL distribution points
2260 *
2261 * This function will deinitialize a CRL distribution points type.
2262 *
2263 * Since: 3.3.0
2264 **/
gnutls_x509_crl_dist_points_deinit(gnutls_x509_crl_dist_points_t cdp)2265 void gnutls_x509_crl_dist_points_deinit(gnutls_x509_crl_dist_points_t cdp)
2266 {
2267 unsigned i;
2268
2269 for (i = 0; i < cdp->size; i++) {
2270 gnutls_free(cdp->points[i].san.data);
2271 }
2272 gnutls_free(cdp->points);
2273 gnutls_free(cdp);
2274 }
2275
2276 /**
2277 * gnutls_x509_crl_dist_points_get:
2278 * @cdp: The CRL distribution points
2279 * @seq: specifies the sequence number of the distribution point (0 for the first one, 1 for the second etc.)
2280 * @type: The name type of the corresponding name (gnutls_x509_subject_alt_name_t)
2281 * @san: The distribution point names (to be treated as constant)
2282 * @reasons: Revocation reasons. An ORed sequence of flags from %gnutls_x509_crl_reason_flags_t.
2283 *
2284 * This function retrieves the individual CRL distribution points (2.5.29.31),
2285 * contained in provided type.
2286 *
2287 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
2288 * if the index is out of bounds, otherwise a negative error value.
2289 **/
2290
gnutls_x509_crl_dist_points_get(gnutls_x509_crl_dist_points_t cdp,unsigned int seq,unsigned int * type,gnutls_datum_t * san,unsigned int * reasons)2291 int gnutls_x509_crl_dist_points_get(gnutls_x509_crl_dist_points_t cdp,
2292 unsigned int seq, unsigned int *type,
2293 gnutls_datum_t * san, unsigned int *reasons)
2294 {
2295 if (seq >= cdp->size)
2296 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
2297
2298 if (reasons)
2299 *reasons = cdp->points[seq].reasons;
2300
2301 if (type)
2302 *type = cdp->points[seq].type;
2303
2304 if (san) {
2305 san->data = cdp->points[seq].san.data;
2306 san->size = cdp->points[seq].san.size;
2307 }
2308
2309 return 0;
2310 }
2311
2312 static
crl_dist_points_set(gnutls_x509_crl_dist_points_t cdp,gnutls_x509_subject_alt_name_t type,const gnutls_datum_t * san,unsigned int reasons)2313 int crl_dist_points_set(gnutls_x509_crl_dist_points_t cdp,
2314 gnutls_x509_subject_alt_name_t type,
2315 const gnutls_datum_t * san, unsigned int reasons)
2316 {
2317 void *tmp;
2318
2319 /* new dist point */
2320 tmp =
2321 gnutls_realloc(cdp->points,
2322 (cdp->size + 1) * sizeof(cdp->points[0]));
2323 if (tmp == NULL) {
2324 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2325 }
2326 cdp->points = tmp;
2327
2328 cdp->points[cdp->size].type = type;
2329 cdp->points[cdp->size].san.data = san->data;
2330 cdp->points[cdp->size].san.size = san->size;
2331 cdp->points[cdp->size].reasons = reasons;
2332
2333 cdp->size++;
2334 return 0;
2335
2336 }
2337
2338 /**
2339 * gnutls_x509_crl_dist_points_set:
2340 * @cdp: The CRL distribution points
2341 * @type: The type of the name (of %gnutls_subject_alt_names_t)
2342 * @san: The point name data
2343 * @reasons: Revocation reasons. An ORed sequence of flags from %gnutls_x509_crl_reason_flags_t.
2344 *
2345 * This function will store the specified CRL distribution point value
2346 * the @cdp type.
2347 *
2348 * Returns: On success, %GNUTLS_E_SUCCESS (0), otherwise a negative error value.
2349 *
2350 * Since: 3.3.0
2351 **/
gnutls_x509_crl_dist_points_set(gnutls_x509_crl_dist_points_t cdp,gnutls_x509_subject_alt_name_t type,const gnutls_datum_t * san,unsigned int reasons)2352 int gnutls_x509_crl_dist_points_set(gnutls_x509_crl_dist_points_t cdp,
2353 gnutls_x509_subject_alt_name_t type,
2354 const gnutls_datum_t * san,
2355 unsigned int reasons)
2356 {
2357 int ret;
2358 gnutls_datum_t t_san;
2359
2360 ret = _gnutls_set_datum(&t_san, san->data, san->size);
2361 if (ret < 0)
2362 return gnutls_assert_val(ret);
2363
2364 ret = crl_dist_points_set(cdp, type, &t_san, reasons);
2365 if (ret < 0) {
2366 gnutls_free(t_san.data);
2367 return gnutls_assert_val(ret);
2368 }
2369
2370 return 0;
2371 }
2372
2373 /**
2374 * gnutls_x509_ext_import_crl_dist_points:
2375 * @ext: the DER encoded extension data
2376 * @cdp: A pointer to an initialized CRL distribution points.
2377 * @flags: should be zero
2378 *
2379 * This function will extract the CRL distribution points extension (2.5.29.31)
2380 * and store it into the provided type.
2381 *
2382 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
2383 *
2384 * Since: 3.3.0
2385 **/
gnutls_x509_ext_import_crl_dist_points(const gnutls_datum_t * ext,gnutls_x509_crl_dist_points_t cdp,unsigned int flags)2386 int gnutls_x509_ext_import_crl_dist_points(const gnutls_datum_t * ext,
2387 gnutls_x509_crl_dist_points_t cdp,
2388 unsigned int flags)
2389 {
2390 int result;
2391 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
2392 char name[MAX_NAME_SIZE];
2393 int len, ret;
2394 uint8_t reasons[2];
2395 unsigned i, type, rflags, j;
2396 gnutls_datum_t san = {NULL, 0};
2397
2398 result = asn1_create_element
2399 (_gnutls_get_pkix(), "PKIX1.CRLDistributionPoints", &c2);
2400 if (result != ASN1_SUCCESS) {
2401 gnutls_assert();
2402 return _gnutls_asn2err(result);
2403 }
2404
2405 result = _asn1_strict_der_decode(&c2, ext->data, ext->size, NULL);
2406
2407 if (result != ASN1_SUCCESS) {
2408 gnutls_assert();
2409 ret = _gnutls_asn2err(result);
2410 goto cleanup;
2411 }
2412
2413 /* Return the different names from the first CRLDistr. point.
2414 * The whole thing is a mess.
2415 */
2416
2417 i = 0;
2418 do {
2419 snprintf(name, sizeof(name), "?%u.reasons", (unsigned)i + 1);
2420
2421 len = sizeof(reasons);
2422 result = asn1_read_value(c2, name, reasons, &len);
2423
2424 if (result != ASN1_VALUE_NOT_FOUND &&
2425 result != ASN1_ELEMENT_NOT_FOUND &&
2426 result != ASN1_SUCCESS) {
2427 gnutls_assert();
2428 ret = _gnutls_asn2err(result);
2429 break;
2430 }
2431
2432 if (result == ASN1_VALUE_NOT_FOUND
2433 || result == ASN1_ELEMENT_NOT_FOUND)
2434 rflags = 0;
2435 else
2436 rflags = reasons[0] | (reasons[1] << 8);
2437
2438 snprintf(name, sizeof(name),
2439 "?%u.distributionPoint.fullName", (unsigned)i + 1);
2440
2441 for (j=0;;j++) {
2442 san.data = NULL;
2443 san.size = 0;
2444
2445 ret =
2446 _gnutls_parse_general_name2(c2, name, j, &san,
2447 &type, 0);
2448 if (j > 0
2449 && ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
2450 ret = 0;
2451 break;
2452 }
2453 if (ret < 0)
2454 break;
2455
2456 ret = crl_dist_points_set(cdp, type, &san, rflags);
2457 if (ret < 0)
2458 break;
2459 san.data = NULL; /* it is now in cdp */
2460 }
2461
2462 i++;
2463 } while (ret >= 0);
2464
2465 if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
2466 gnutls_assert();
2467 gnutls_free(san.data);
2468 goto cleanup;
2469 }
2470
2471 ret = 0;
2472 cleanup:
2473 asn1_delete_structure(&c2);
2474 return ret;
2475 }
2476
2477 /**
2478 * gnutls_x509_ext_export_crl_dist_points:
2479 * @cdp: A pointer to an initialized CRL distribution points.
2480 * @ext: The DER-encoded extension data; must be freed using gnutls_free().
2481 *
2482 * This function will convert the provided policies, to a certificate policy
2483 * DER encoded extension (2.5.29.31).
2484 *
2485 * The @ext data will be allocated using gnutls_malloc().
2486 *
2487 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
2488 *
2489 * Since: 3.3.0
2490 **/
gnutls_x509_ext_export_crl_dist_points(gnutls_x509_crl_dist_points_t cdp,gnutls_datum_t * ext)2491 int gnutls_x509_ext_export_crl_dist_points(gnutls_x509_crl_dist_points_t cdp,
2492 gnutls_datum_t * ext)
2493 {
2494 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
2495 int result;
2496 uint8_t reasons[2];
2497 unsigned i;
2498
2499 result =
2500 asn1_create_element(_gnutls_get_pkix(),
2501 "PKIX1.CRLDistributionPoints", &c2);
2502 if (result != ASN1_SUCCESS) {
2503 gnutls_assert();
2504 result = _gnutls_asn2err(result);
2505 goto cleanup;
2506 }
2507
2508 for (i = 0; i < cdp->size; i++) {
2509
2510 if (i == 0
2511 || cdp->points[i].reasons != cdp->points[i - 1].reasons) {
2512 result = asn1_write_value(c2, "", "NEW", 1);
2513 if (result != ASN1_SUCCESS) {
2514 gnutls_assert();
2515 result = _gnutls_asn2err(result);
2516 goto cleanup;
2517 }
2518
2519 if (cdp->points[i].reasons) {
2520 reasons[0] = cdp->points[i].reasons & 0xff;
2521 reasons[1] = cdp->points[i].reasons >> 8;
2522
2523 result =
2524 asn1_write_value(c2, "?LAST.reasons",
2525 reasons, 2);
2526 } else {
2527 result =
2528 asn1_write_value(c2, "?LAST.reasons", NULL,
2529 0);
2530 }
2531
2532 if (result != ASN1_SUCCESS) {
2533 gnutls_assert();
2534 result = _gnutls_asn2err(result);
2535 goto cleanup;
2536 }
2537
2538 result =
2539 asn1_write_value(c2, "?LAST.cRLIssuer", NULL, 0);
2540 if (result != ASN1_SUCCESS) {
2541 gnutls_assert();
2542 result = _gnutls_asn2err(result);
2543 goto cleanup;
2544 }
2545 /* When used as type CHOICE.
2546 */
2547 result =
2548 asn1_write_value(c2, "?LAST.distributionPoint",
2549 "fullName", 1);
2550 if (result != ASN1_SUCCESS) {
2551 gnutls_assert();
2552 result = _gnutls_asn2err(result);
2553 goto cleanup;
2554 }
2555 }
2556
2557 result =
2558 _gnutls_write_new_general_name(c2,
2559 "?LAST.distributionPoint.fullName",
2560 cdp->points[i].type,
2561 cdp->points[i].san.data,
2562 cdp->points[i].san.size);
2563 if (result < 0) {
2564 gnutls_assert();
2565 goto cleanup;
2566 }
2567 }
2568
2569 result = _gnutls_x509_der_encode(c2, "", ext, 0);
2570 if (result < 0) {
2571 gnutls_assert();
2572 goto cleanup;
2573 }
2574
2575 result = 0;
2576
2577 cleanup:
2578 asn1_delete_structure(&c2);
2579
2580 return result;
2581
2582 }
2583
2584 struct gnutls_x509_aia_st {
2585 struct {
2586 gnutls_datum_t oid;
2587 unsigned int san_type;
2588 gnutls_datum_t san;
2589 } *aia;
2590 unsigned int size;
2591 };
2592
2593 /**
2594 * gnutls_x509_aia_init:
2595 * @aia: The authority info access
2596 *
2597 * This function will initialize an authority info access type.
2598 *
2599 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
2600 *
2601 * Since: 3.3.0
2602 **/
gnutls_x509_aia_init(gnutls_x509_aia_t * aia)2603 int gnutls_x509_aia_init(gnutls_x509_aia_t * aia)
2604 {
2605 *aia = gnutls_calloc(1, sizeof(struct gnutls_x509_aia_st));
2606 if (*aia == NULL)
2607 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2608
2609 return 0;
2610 }
2611
2612 /**
2613 * gnutls_x509_aia_deinit:
2614 * @aia: The authority info access
2615 *
2616 * This function will deinitialize an authority info access type.
2617 *
2618 * Since: 3.3.0
2619 **/
gnutls_x509_aia_deinit(gnutls_x509_aia_t aia)2620 void gnutls_x509_aia_deinit(gnutls_x509_aia_t aia)
2621 {
2622 unsigned i;
2623
2624 for (i = 0; i < aia->size; i++) {
2625 gnutls_free(aia->aia[i].san.data);
2626 gnutls_free(aia->aia[i].oid.data);
2627 }
2628 gnutls_free(aia->aia);
2629 gnutls_free(aia);
2630 }
2631
2632 /**
2633 * gnutls_x509_aia_get:
2634 * @aia: The authority info access
2635 * @seq: specifies the sequence number of the access descriptor (0 for the first one, 1 for the second etc.)
2636 * @oid: the type of available data; to be treated as constant.
2637 * @san_type: Will hold the type of the name of %gnutls_subject_alt_names_t (may be null).
2638 * @san: the access location name; to be treated as constant (may be null).
2639 *
2640 * This function reads from the Authority Information Access type.
2641 *
2642 * The @seq input parameter is used to indicate which member of the
2643 * sequence the caller is interested in. The first member is 0, the
2644 * second member 1 and so on. When the @seq value is out of bounds,
2645 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
2646 *
2647 * Typically @oid is %GNUTLS_OID_AD_CAISSUERS or %GNUTLS_OID_AD_OCSP.
2648 *
2649 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
2650 *
2651 * Since: 3.3.0
2652 **/
gnutls_x509_aia_get(gnutls_x509_aia_t aia,unsigned int seq,gnutls_datum_t * oid,unsigned * san_type,gnutls_datum_t * san)2653 int gnutls_x509_aia_get(gnutls_x509_aia_t aia, unsigned int seq,
2654 gnutls_datum_t *oid,
2655 unsigned *san_type,
2656 gnutls_datum_t *san)
2657 {
2658 if (seq >= aia->size)
2659 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
2660
2661 if (san_type)
2662 *san_type = aia->aia[seq].san_type;
2663 if (san) {
2664 san->data = aia->aia[seq].san.data;
2665 san->size = aia->aia[seq].san.size;
2666 }
2667
2668 if (oid) {
2669 oid->data = aia->aia[seq].oid.data;
2670 oid->size = aia->aia[seq].oid.size;
2671 }
2672
2673 return 0;
2674 }
2675
_gnutls_alt_name_process(gnutls_datum_t * out,unsigned type,const gnutls_datum_t * san,unsigned raw)2676 int _gnutls_alt_name_process(gnutls_datum_t *out, unsigned type, const gnutls_datum_t *san, unsigned raw)
2677 {
2678 int ret;
2679 if (type == GNUTLS_SAN_DNSNAME && !raw) {
2680 ret = gnutls_idna_map((char*)san->data, san->size, out, 0);
2681 if (ret < 0) {
2682 return gnutls_assert_val(ret);
2683 }
2684 } else if (type == GNUTLS_SAN_RFC822NAME && !raw) {
2685 ret = _gnutls_idna_email_map((char*)san->data, san->size, out);
2686 if (ret < 0) {
2687 return gnutls_assert_val(ret);
2688 }
2689 } else if (type == GNUTLS_SAN_URI && !raw) {
2690 if (!_gnutls_str_is_print((char*)san->data, san->size)) {
2691 _gnutls_debug_log("non-ASCII URIs are not supported\n");
2692 return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
2693 } else {
2694 ret = _gnutls_set_strdatum(out, san->data, san->size);
2695 if (ret < 0)
2696 return gnutls_assert_val(ret);
2697 }
2698 } else {
2699 ret = _gnutls_set_strdatum(out, san->data, san->size);
2700 if (ret < 0)
2701 return gnutls_assert_val(ret);
2702 }
2703
2704 return 0;
2705 }
2706
2707 /**
2708 * gnutls_x509_aia_set:
2709 * @aia: The authority info access
2710 * @oid: the type of data.
2711 * @san_type: The type of the name (of %gnutls_subject_alt_names_t)
2712 * @san: The alternative name data
2713 * @othername_oid: The object identifier if @san_type is %GNUTLS_SAN_OTHERNAME
2714 *
2715 * This function will store the specified alternative name in
2716 * the @aia type.
2717 *
2718 * Typically the value for @oid should be %GNUTLS_OID_AD_OCSP, or
2719 * %GNUTLS_OID_AD_CAISSUERS.
2720 *
2721 * Since version 3.5.7 the %GNUTLS_SAN_RFC822NAME, and %GNUTLS_SAN_DNSNAME,
2722 * are converted to ACE format when necessary.
2723 *
2724 * Returns: On success, %GNUTLS_E_SUCCESS (0), otherwise a negative error value.
2725 *
2726 * Since: 3.3.0
2727 **/
gnutls_x509_aia_set(gnutls_x509_aia_t aia,const char * oid,unsigned san_type,const gnutls_datum_t * san)2728 int gnutls_x509_aia_set(gnutls_x509_aia_t aia,
2729 const char *oid,
2730 unsigned san_type,
2731 const gnutls_datum_t * san)
2732 {
2733 int ret;
2734 void *tmp;
2735 unsigned indx;
2736
2737 tmp = gnutls_realloc(aia->aia, (aia->size + 1) * sizeof(aia->aia[0]));
2738 if (tmp == NULL) {
2739 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2740 }
2741 aia->aia = tmp;
2742 indx = aia->size;
2743
2744 aia->aia[indx].san_type = san_type;
2745 if (oid) {
2746 aia->aia[indx].oid.data = (void*)gnutls_strdup(oid);
2747 aia->aia[indx].oid.size = strlen(oid);
2748 } else {
2749 aia->aia[indx].oid.data = NULL;
2750 aia->aia[indx].oid.size = 0;
2751 }
2752
2753 ret = _gnutls_alt_name_process(&aia->aia[indx].san, san_type, san, 0);
2754 if (ret < 0)
2755 return gnutls_assert_val(ret);
2756
2757 aia->size++;
2758
2759 return 0;
2760 }
2761
2762
parse_aia(ASN1_TYPE c2,gnutls_x509_aia_t aia)2763 static int parse_aia(ASN1_TYPE c2, gnutls_x509_aia_t aia)
2764 {
2765 int len;
2766 char nptr[MAX_NAME_SIZE];
2767 int ret, result;
2768 char tmpoid[MAX_OID_SIZE];
2769 void * tmp;
2770 unsigned i, indx;
2771
2772 for (i = 1;; i++) {
2773 snprintf(nptr, sizeof(nptr), "?%u.accessMethod", i);
2774
2775 len = sizeof(tmpoid);
2776 result = asn1_read_value(c2, nptr, tmpoid, &len);
2777 if (result == ASN1_VALUE_NOT_FOUND
2778 || result == ASN1_ELEMENT_NOT_FOUND) {
2779 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2780 break;
2781 }
2782
2783 if (result != ASN1_SUCCESS) {
2784 gnutls_assert();
2785 return _gnutls_asn2err(result);
2786 }
2787
2788 indx = aia->size;
2789 tmp = gnutls_realloc(aia->aia, (aia->size + 1) * sizeof(aia->aia[0]));
2790 if (tmp == NULL) {
2791 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2792 }
2793 aia->aia = tmp;
2794
2795 snprintf(nptr, sizeof(nptr), "?%u.accessLocation", i);
2796
2797
2798 ret = _gnutls_parse_general_name2(c2, nptr, -1, &aia->aia[indx].san,
2799 &aia->aia[indx].san_type, 0);
2800 if (ret < 0)
2801 break;
2802
2803 /* we do the strdup after parsing to avoid a memory leak */
2804 aia->aia[indx].oid.data = (void*)gnutls_strdup(tmpoid);
2805 aia->aia[indx].oid.size = strlen(tmpoid);
2806
2807 aia->size++;
2808
2809 if (aia->aia[indx].oid.data == NULL) {
2810 gnutls_assert();
2811 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
2812 }
2813 }
2814
2815 if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
2816 return ret;
2817 }
2818
2819 return 0;
2820 }
2821
2822 /**
2823 * gnutls_x509_ext_import_aia:
2824 * @ext: The DER-encoded extension data
2825 * @aia: The authority info access
2826 * @flags: should be zero
2827 *
2828 * This function extracts the Authority Information Access (AIA)
2829 * extension from the provided DER-encoded data; see RFC 5280 section 4.2.2.1
2830 * for more information on the extension. The
2831 * AIA extension holds a sequence of AccessDescription (AD) data.
2832 *
2833 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
2834 *
2835 * Since: 3.3.0
2836 **/
gnutls_x509_ext_import_aia(const gnutls_datum_t * ext,gnutls_x509_aia_t aia,unsigned int flags)2837 int gnutls_x509_ext_import_aia(const gnutls_datum_t * ext,
2838 gnutls_x509_aia_t aia,
2839 unsigned int flags)
2840 {
2841 int ret;
2842 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
2843
2844 if (ext->size == 0 || ext->data == NULL) {
2845 gnutls_assert();
2846 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
2847 }
2848
2849 ret = asn1_create_element(_gnutls_get_pkix(),
2850 "PKIX1.AuthorityInfoAccessSyntax", &c2);
2851 if (ret != ASN1_SUCCESS) {
2852 gnutls_assert();
2853 return _gnutls_asn2err(ret);
2854 }
2855
2856 ret = _asn1_strict_der_decode(&c2, ext->data, ext->size, NULL);
2857 if (ret != ASN1_SUCCESS) {
2858 gnutls_assert();
2859 ret = _gnutls_asn2err(ret);
2860 goto cleanup;
2861 }
2862
2863 ret = parse_aia(c2, aia);
2864 if (ret < 0) {
2865 gnutls_assert();
2866 }
2867
2868 cleanup:
2869 asn1_delete_structure(&c2);
2870
2871 return ret;
2872
2873 }
2874
2875 /**
2876 * gnutls_x509_ext_export_aia:
2877 * @aia: The authority info access
2878 * @ext: The DER-encoded extension data; must be freed using gnutls_free().
2879 *
2880 * This function will DER encode the Authority Information Access (AIA)
2881 * extension; see RFC 5280 section 4.2.2.1 for more information on the
2882 * extension.
2883 *
2884 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2885 * negative error value.
2886 *
2887 * Since: 3.3.0
2888 **/
gnutls_x509_ext_export_aia(gnutls_x509_aia_t aia,gnutls_datum_t * ext)2889 int gnutls_x509_ext_export_aia(gnutls_x509_aia_t aia,
2890 gnutls_datum_t * ext)
2891 {
2892 int ret, result;
2893 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
2894 unsigned int i;
2895
2896 ret = asn1_create_element(_gnutls_get_pkix(),
2897 "PKIX1.AuthorityInfoAccessSyntax", &c2);
2898 if (ret != ASN1_SUCCESS) {
2899 gnutls_assert();
2900 return _gnutls_asn2err(ret);
2901 }
2902
2903 /* 1. create a new element.
2904 */
2905 for (i=0;i<aia->size;i++) {
2906 result = asn1_write_value(c2, "", "NEW", 1);
2907 if (result != ASN1_SUCCESS) {
2908 gnutls_assert();
2909 ret = _gnutls_asn2err(result);
2910 goto cleanup;
2911 }
2912
2913 /* 2. Add the OID.
2914 */
2915 result = asn1_write_value(c2, "?LAST.accessMethod", aia->aia[i].oid.data, 1);
2916 if (result != ASN1_SUCCESS) {
2917 gnutls_assert();
2918 ret = _gnutls_asn2err(result);
2919 goto cleanup;
2920 }
2921
2922 ret =
2923 _gnutls_write_general_name(c2,
2924 "?LAST.accessLocation",
2925 aia->aia[i].san_type,
2926 aia->aia[i].san.data,
2927 aia->aia[i].san.size);
2928 if (ret < 0) {
2929 gnutls_assert();
2930 goto cleanup;
2931 }
2932 }
2933
2934 ret = _gnutls_x509_der_encode(c2, "", ext, 0);
2935 if (ret < 0) {
2936 gnutls_assert();
2937 goto cleanup;
2938 }
2939
2940 cleanup:
2941 asn1_delete_structure(&c2);
2942
2943 return ret;
2944 }
2945
2946
2947 struct gnutls_x509_key_purposes_st {
2948 gnutls_datum_t oid[MAX_ENTRIES];
2949 unsigned int size;
2950 };
2951
2952 /**
2953 * gnutls_subject_alt_names_init:
2954 * @p: The key purposes
2955 *
2956 * This function will initialize an alternative names type.
2957 *
2958 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
2959 *
2960 * Since: 3.3.0
2961 **/
gnutls_x509_key_purpose_init(gnutls_x509_key_purposes_t * p)2962 int gnutls_x509_key_purpose_init(gnutls_x509_key_purposes_t * p)
2963 {
2964 *p = gnutls_calloc(1, sizeof(struct gnutls_x509_key_purposes_st));
2965 if (*p == NULL) {
2966 gnutls_assert();
2967 return GNUTLS_E_MEMORY_ERROR;
2968 }
2969
2970 return 0;
2971 }
2972
key_purposes_deinit(gnutls_x509_key_purposes_t p)2973 static void key_purposes_deinit(gnutls_x509_key_purposes_t p)
2974 {
2975 unsigned int i;
2976
2977 for (i = 0; i < p->size; i++) {
2978 gnutls_free(p->oid[i].data);
2979 }
2980 }
2981
2982 /**
2983 * gnutls_x509_key_purpose_deinit:
2984 * @p: The key purposes
2985 *
2986 * This function will deinitialize a key purposes type.
2987 *
2988 * Since: 3.3.0
2989 **/
gnutls_x509_key_purpose_deinit(gnutls_x509_key_purposes_t p)2990 void gnutls_x509_key_purpose_deinit(gnutls_x509_key_purposes_t p)
2991 {
2992 key_purposes_deinit(p);
2993 gnutls_free(p);
2994 }
2995
2996 /**
2997 * gnutls_x509_key_purpose_set:
2998 * @p: The key purposes
2999 * @oid: The object identifier of the key purpose
3000 *
3001 * This function will store the specified key purpose in the
3002 * purposes.
3003 *
3004 * Returns: On success, %GNUTLS_E_SUCCESS (0), otherwise a negative error value.
3005 *
3006 * Since: 3.3.0
3007 **/
gnutls_x509_key_purpose_set(gnutls_x509_key_purposes_t p,const char * oid)3008 int gnutls_x509_key_purpose_set(gnutls_x509_key_purposes_t p, const char *oid)
3009 {
3010 if (p->size + 1 > MAX_ENTRIES)
3011 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
3012
3013 p->oid[p->size].data = (void*)gnutls_strdup(oid);
3014 if (p->oid[p->size].data == NULL)
3015 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
3016
3017 p->oid[p->size].size = strlen(oid);
3018 p->size++;
3019
3020 return 0;
3021 }
3022
3023 /**
3024 * gnutls_x509_key_purpose_get:
3025 * @p: The key purposes
3026 * @idx: The index of the key purpose to retrieve
3027 * @oid: Will hold the object identifier of the key purpose (to be treated as constant)
3028 *
3029 * This function will retrieve the specified by the index key purpose in the
3030 * purposes type. The object identifier will be a null terminated string.
3031 *
3032 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
3033 * if the index is out of bounds, otherwise a negative error value.
3034 *
3035 * Since: 3.3.0
3036 **/
gnutls_x509_key_purpose_get(gnutls_x509_key_purposes_t p,unsigned idx,gnutls_datum_t * oid)3037 int gnutls_x509_key_purpose_get(gnutls_x509_key_purposes_t p, unsigned idx, gnutls_datum_t *oid)
3038 {
3039 if (idx >= p->size)
3040 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
3041
3042 oid->data = p->oid[idx].data;
3043 oid->size = p->oid[idx].size;
3044
3045 return 0;
3046 }
3047
3048 /**
3049 * gnutls_x509_ext_import_key_purposes:
3050 * @ext: The DER-encoded extension data
3051 * @p: The key purposes
3052 * @flags: should be zero
3053 *
3054 * This function will extract the key purposes in the provided DER-encoded
3055 * ExtKeyUsageSyntax PKIX extension, to a %gnutls_x509_key_purposes_t type.
3056 * The data must be initialized.
3057 *
3058 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
3059 *
3060 * Since: 3.3.0
3061 **/
gnutls_x509_ext_import_key_purposes(const gnutls_datum_t * ext,gnutls_x509_key_purposes_t p,unsigned int flags)3062 int gnutls_x509_ext_import_key_purposes(const gnutls_datum_t * ext,
3063 gnutls_x509_key_purposes_t p,
3064 unsigned int flags)
3065 {
3066 char tmpstr[MAX_NAME_SIZE];
3067 int result, ret;
3068 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
3069 gnutls_datum_t oid = {NULL, 0};
3070 unsigned i;
3071
3072 result = asn1_create_element
3073 (_gnutls_get_pkix(), "PKIX1.ExtKeyUsageSyntax", &c2);
3074 if (result != ASN1_SUCCESS) {
3075 gnutls_assert();
3076 return _gnutls_asn2err(result);
3077 }
3078
3079 result = _asn1_strict_der_decode(&c2, ext->data, ext->size, NULL);
3080 if (result != ASN1_SUCCESS) {
3081 gnutls_assert();
3082 ret = _gnutls_asn2err(result);
3083 goto cleanup;
3084 }
3085
3086 key_purposes_deinit(p);
3087 i = 0;
3088 p->size = 0;
3089
3090 for (;i<MAX_ENTRIES;i++) {
3091 /* create a string like "?1"
3092 */
3093 snprintf(tmpstr, sizeof(tmpstr), "?%u", i+1);
3094
3095 ret = _gnutls_x509_read_value(c2, tmpstr, &oid);
3096 if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) {
3097 break;
3098 }
3099
3100 if (ret < 0) {
3101 gnutls_assert();
3102 goto cleanup;
3103 }
3104
3105 p->oid[i].data = oid.data;
3106 p->oid[i].size = oid.size;
3107
3108 oid.data = NULL;
3109 oid.size = 0;
3110 p->size++;
3111 }
3112
3113 ret = 0;
3114 cleanup:
3115 gnutls_free(oid.data);
3116 asn1_delete_structure(&c2);
3117
3118 return ret;
3119
3120 }
3121
3122 /**
3123 * gnutls_x509_ext_export_key_purposes:
3124 * @p: The key purposes
3125 * @ext: The DER-encoded extension data; must be freed using gnutls_free().
3126 *
3127 * This function will convert the key purposes type to a
3128 * DER-encoded PKIX ExtKeyUsageSyntax (2.5.29.37) extension. The output data in
3129 * @ext will be allocated using gnutls_malloc().
3130 *
3131 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
3132 *
3133 * Since: 3.3.0
3134 **/
gnutls_x509_ext_export_key_purposes(gnutls_x509_key_purposes_t p,gnutls_datum_t * ext)3135 int gnutls_x509_ext_export_key_purposes(gnutls_x509_key_purposes_t p,
3136 gnutls_datum_t * ext)
3137 {
3138 int result, ret;
3139 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
3140 unsigned i;
3141
3142 result = asn1_create_element
3143 (_gnutls_get_pkix(), "PKIX1.ExtKeyUsageSyntax", &c2);
3144 if (result != ASN1_SUCCESS) {
3145 gnutls_assert();
3146 return _gnutls_asn2err(result);
3147 }
3148
3149 /* generate the extension.
3150 */
3151 for (i=0;i<p->size;i++) {
3152 /* 1. create a new element.
3153 */
3154 result = asn1_write_value(c2, "", "NEW", 1);
3155 if (result != ASN1_SUCCESS) {
3156 gnutls_assert();
3157 ret = _gnutls_asn2err(result);
3158 goto cleanup;
3159 }
3160
3161 /* 2. Add the OID.
3162 */
3163 result = asn1_write_value(c2, "?LAST", p->oid[i].data, 1);
3164 if (result != ASN1_SUCCESS) {
3165 gnutls_assert();
3166 ret = _gnutls_asn2err(result);
3167 goto cleanup;
3168 }
3169 }
3170
3171 ret = _gnutls_x509_der_encode(c2, "", ext, 0);
3172 if (ret < 0) {
3173 gnutls_assert();
3174 goto cleanup;
3175 }
3176
3177 ret = 0;
3178
3179 cleanup:
3180 asn1_delete_structure(&c2);
3181 return ret;
3182 }
3183
3184 /**
3185 * gnutls_ext_deinit:
3186 * @ext: The extensions structure
3187 *
3188 * This function will deinitialize an extensions structure.
3189 *
3190 * Since: 3.3.8
3191 **/
gnutls_x509_ext_deinit(gnutls_x509_ext_st * ext)3192 void gnutls_x509_ext_deinit(gnutls_x509_ext_st *ext)
3193 {
3194 gnutls_free(ext->oid);
3195 gnutls_free(ext->data.data);
3196 }
3197
_gnutls_x509_decode_ext(const gnutls_datum_t * der,gnutls_x509_ext_st * out)3198 int _gnutls_x509_decode_ext(const gnutls_datum_t *der, gnutls_x509_ext_st *out)
3199 {
3200 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
3201 char str_critical[10];
3202 char oid[MAX_OID_SIZE];
3203 int result, len, ret;
3204
3205 memset(out, 0, sizeof(*out));
3206
3207 /* decode der */
3208 result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.Extension", &c2);
3209 if (result != ASN1_SUCCESS) {
3210 gnutls_assert();
3211 return _gnutls_asn2err(result);
3212 }
3213
3214 result = _asn1_strict_der_decode(&c2, der->data, der->size, NULL);
3215 if (result != ASN1_SUCCESS) {
3216 gnutls_assert();
3217 ret = _gnutls_asn2err(result);
3218 goto cleanup;
3219 }
3220
3221 len = sizeof(oid)-1;
3222 result = asn1_read_value(c2, "extnID", oid, &len);
3223 if (result != ASN1_SUCCESS) {
3224 gnutls_assert();
3225 ret = _gnutls_asn2err(result);
3226 goto cleanup;
3227 }
3228
3229 len = sizeof(str_critical)-1;
3230 result = asn1_read_value(c2, "critical", str_critical, &len);
3231 if (result != ASN1_SUCCESS) {
3232 gnutls_assert();
3233 ret = _gnutls_asn2err(result);
3234 goto cleanup;
3235 }
3236
3237 if (str_critical[0] == 'T')
3238 out->critical = 1;
3239 else
3240 out->critical = 0;
3241
3242 ret = _gnutls_x509_read_value(c2, "extnValue", &out->data);
3243 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE || ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) {
3244 out->data.data = NULL;
3245 out->data.size = 0;
3246 } else if (ret < 0) {
3247 gnutls_assert();
3248 goto fail;
3249 }
3250
3251 out->oid = gnutls_strdup(oid);
3252 if (out->oid == NULL) {
3253 ret = GNUTLS_E_MEMORY_ERROR;
3254 goto fail;
3255 }
3256
3257 ret = 0;
3258 goto cleanup;
3259 fail:
3260 memset(out, 0, sizeof(*out));
3261 cleanup:
3262 asn1_delete_structure(&c2);
3263 return ret;
3264
3265 }
3266
3267 /* flags can be zero or GNUTLS_EXT_FLAG_APPEND
3268 */
parse_tlsfeatures(ASN1_TYPE c2,gnutls_x509_tlsfeatures_t f,unsigned flags)3269 static int parse_tlsfeatures(ASN1_TYPE c2, gnutls_x509_tlsfeatures_t f, unsigned flags)
3270 {
3271 char nptr[MAX_NAME_SIZE];
3272 int result;
3273 unsigned i, indx, j;
3274 unsigned int feature;
3275
3276 if (!(flags & GNUTLS_EXT_FLAG_APPEND))
3277 f->size = 0;
3278
3279 for (i = 1;; i++) {
3280 unsigned skip = 0;
3281 snprintf(nptr, sizeof(nptr), "?%u", i);
3282
3283 result = _gnutls_x509_read_uint(c2, nptr, &feature);
3284
3285 if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND || result == GNUTLS_E_ASN1_VALUE_NOT_FOUND) {
3286 break;
3287 }
3288 else if (result != GNUTLS_E_SUCCESS) {
3289 gnutls_assert();
3290 return _gnutls_asn2err(result);
3291 }
3292
3293 if (feature > UINT16_MAX) {
3294 gnutls_assert();
3295 return GNUTLS_E_CERTIFICATE_ERROR;
3296 }
3297
3298 /* skip duplicates */
3299 for (j=0;j<f->size;j++) {
3300 if (f->feature[j] == feature) {
3301 skip = 1;
3302 break;
3303 }
3304 }
3305
3306 if (!skip) {
3307 if (f->size >= sizeof(f->feature)/sizeof(f->feature[0])) {
3308 gnutls_assert();
3309 return GNUTLS_E_INTERNAL_ERROR;
3310 }
3311
3312 indx = f->size;
3313 f->feature[indx] = feature;
3314 f->size++;
3315 }
3316 }
3317
3318 return 0;
3319 }
3320
3321 /**
3322 * gnutls_x509_ext_import_tlsfeatures:
3323 * @ext: The DER-encoded extension data
3324 * @f: The features structure
3325 * @flags: zero or %GNUTLS_EXT_FLAG_APPEND
3326 *
3327 * This function will export the features in the provided DER-encoded
3328 * TLS Features PKIX extension, to a %gnutls_x509_tlsfeatures_t type. @f
3329 * must be initialized.
3330 *
3331 * When the @flags is set to %GNUTLS_EXT_FLAG_APPEND,
3332 * then if the @features structure is empty this function will behave
3333 * identically as if the flag was not set. Otherwise if there are elements
3334 * in the @features structure then they will be merged with.
3335 *
3336 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
3337 *
3338 * Since: 3.5.1
3339 **/
gnutls_x509_ext_import_tlsfeatures(const gnutls_datum_t * ext,gnutls_x509_tlsfeatures_t f,unsigned int flags)3340 int gnutls_x509_ext_import_tlsfeatures(const gnutls_datum_t * ext,
3341 gnutls_x509_tlsfeatures_t f,
3342 unsigned int flags)
3343 {
3344 int ret;
3345 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
3346
3347 if (ext->size == 0 || ext->data == NULL) {
3348 gnutls_assert();
3349 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
3350 }
3351
3352 ret = asn1_create_element(_gnutls_get_pkix(),
3353 "PKIX1.TlsFeatures", &c2);
3354 if (ret != ASN1_SUCCESS) {
3355 gnutls_assert();
3356 return _gnutls_asn2err(ret);
3357 }
3358
3359 ret = _asn1_strict_der_decode(&c2, ext->data, ext->size, NULL);
3360 if (ret != ASN1_SUCCESS) {
3361 gnutls_assert();
3362 ret = _gnutls_asn2err(ret);
3363 goto cleanup;
3364 }
3365
3366 ret = parse_tlsfeatures(c2, f, flags);
3367 if (ret < 0) {
3368 gnutls_assert();
3369 }
3370
3371 cleanup:
3372 asn1_delete_structure(&c2);
3373
3374 return ret;
3375 }
3376
3377 /**
3378 * gnutls_x509_ext_export_tlsfeatures:
3379 * @f: The features structure
3380 * @ext: The DER-encoded extension data; must be freed using gnutls_free().
3381 *
3382 * This function will convert the provided TLS features structure structure to a
3383 * DER-encoded TLS features PKIX extension. The output data in @ext will be allocated using
3384 * gnutls_malloc().
3385 *
3386 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
3387 *
3388 * Since: 3.5.1
3389 **/
gnutls_x509_ext_export_tlsfeatures(gnutls_x509_tlsfeatures_t f,gnutls_datum_t * ext)3390 int gnutls_x509_ext_export_tlsfeatures(gnutls_x509_tlsfeatures_t f,
3391 gnutls_datum_t * ext)
3392 {
3393 if (f == NULL) {
3394 gnutls_assert();
3395 return GNUTLS_E_INVALID_REQUEST;
3396 }
3397
3398 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
3399 int ret;
3400 unsigned i;
3401
3402 ret = asn1_create_element(_gnutls_get_pkix(), "PKIX1.TlsFeatures", &c2);
3403 if (ret != ASN1_SUCCESS) {
3404 gnutls_assert();
3405 return _gnutls_asn2err(ret);
3406 }
3407
3408 for (i = 0; i < f->size; ++i) {
3409
3410 ret = asn1_write_value(c2, "", "NEW", 1);
3411 if (ret != ASN1_SUCCESS) {
3412 gnutls_assert();
3413 ret = _gnutls_asn2err(ret);
3414 goto cleanup;
3415 }
3416
3417 ret = _gnutls_x509_write_uint32(c2, "?LAST", f->feature[i]);
3418 if (ret != GNUTLS_E_SUCCESS) {
3419 gnutls_assert();
3420 goto cleanup;
3421 }
3422 }
3423
3424 ret = _gnutls_x509_der_encode(c2, "", ext, 0);
3425 if (ret < 0) {
3426 gnutls_assert();
3427 goto cleanup;
3428 }
3429
3430 ret = 0;
3431
3432 cleanup:
3433 asn1_delete_structure(&c2);
3434 return ret;
3435 }
3436
3437 /**
3438 * gnutls_x509_tlsfeatures_add:
3439 * @f: The TLS features
3440 * @feature: The feature to add
3441 *
3442 * This function will append a feature to the X.509 TLS features
3443 * extension structure.
3444 *
3445 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
3446 * otherwise a negative error value.
3447 *
3448 * Since: 3.5.1
3449 **/
gnutls_x509_tlsfeatures_add(gnutls_x509_tlsfeatures_t f,unsigned int feature)3450 int gnutls_x509_tlsfeatures_add(gnutls_x509_tlsfeatures_t f, unsigned int feature)
3451 {
3452 if (f == NULL) {
3453 gnutls_assert();
3454 return GNUTLS_E_INVALID_REQUEST;
3455 }
3456
3457 if (feature > UINT16_MAX)
3458 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
3459
3460 if (f->size >= sizeof(f->feature)/sizeof(f->feature[0]))
3461 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
3462
3463 f->feature[f->size++] = feature;
3464
3465 return 0;
3466 }
3467