Line data Source code
1 : /*
2 : * Copyright (C) 2003-2014 Free Software Foundation, Inc.
3 : *
4 : * Author: Nikos Mavrogiannopoulos
5 : *
6 : * This file is part of GnuTLS.
7 : *
8 : * The GnuTLS is free software; you can redistribute it and/or
9 : * modify it under the terms of the GNU Lesser General Public License
10 : * as published by the Free Software Foundation; either version 2.1 of
11 : * the License, or (at your option) any later version.
12 : *
13 : * This library is distributed in the hope that it will be useful, but
14 : * WITHOUT ANY WARRANTY; without even the implied warranty of
15 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : * Lesser General Public License for more details.
17 : *
18 : * You should have received a copy of the GNU Lesser General Public License
19 : * along with this program. If not, see <https://www.gnu.org/licenses/>
20 : *
21 : */
22 :
23 : /* Functions that relate to the X.509 extension parsing.
24 : */
25 :
26 : #include "gnutls_int.h"
27 : #include "errors.h"
28 : #include <global.h>
29 : #include <libtasn1.h>
30 : #include <common.h>
31 : #include <gnutls/x509-ext.h>
32 : #include <gnutls/x509.h>
33 : #include <x509_int.h>
34 : #include <datum.h>
35 :
36 : int
37 99091 : _gnutls_get_extension(ASN1_TYPE asn, const char *root,
38 : const char *extension_id, int indx,
39 : gnutls_datum_t * ret, unsigned int *_critical)
40 : {
41 99091 : int k, result, len;
42 99091 : char name[MAX_NAME_SIZE], name2[MAX_NAME_SIZE];
43 99091 : char str_critical[10];
44 99091 : int critical = 0;
45 99091 : char extnID[MAX_OID_SIZE];
46 99091 : gnutls_datum_t value;
47 99091 : int indx_counter = 0;
48 :
49 99091 : ret->data = NULL;
50 99091 : ret->size = 0;
51 :
52 99091 : k = 0;
53 406858 : do {
54 406858 : k++;
55 :
56 406858 : snprintf(name, sizeof(name), "%s.?%u", root, k);
57 :
58 406858 : _gnutls_str_cpy(name2, sizeof(name2), name);
59 406858 : _gnutls_str_cat(name2, sizeof(name2), ".extnID");
60 :
61 406858 : len = sizeof(extnID) - 1;
62 406858 : result = asn1_read_value(asn, name2, extnID, &len);
63 :
64 406858 : if (result == ASN1_ELEMENT_NOT_FOUND) {
65 : break;
66 355353 : } else if (result != ASN1_SUCCESS) {
67 4 : gnutls_assert();
68 4 : return _gnutls_asn2err(result);
69 : }
70 :
71 : /* Handle Extension
72 : */
73 355349 : if (strcmp(extnID, extension_id) == 0
74 47582 : && indx == indx_counter++) {
75 : /* extension was found
76 : */
77 :
78 : /* read the critical status.
79 : */
80 47582 : _gnutls_str_cpy(name2, sizeof(name2), name);
81 47582 : _gnutls_str_cat(name2, sizeof(name2), ".critical");
82 :
83 47582 : len = sizeof(str_critical);
84 47582 : result =
85 47582 : asn1_read_value(asn, name2,
86 : str_critical, &len);
87 :
88 47582 : if (result == ASN1_ELEMENT_NOT_FOUND) {
89 0 : gnutls_assert();
90 : break;
91 47582 : } else if (result != ASN1_SUCCESS) {
92 0 : gnutls_assert();
93 0 : return _gnutls_asn2err(result);
94 : }
95 :
96 47582 : if (str_critical[0] == 'T')
97 : critical = 1;
98 : else
99 23945 : critical = 0;
100 :
101 : /* read the value.
102 : */
103 47582 : _gnutls_str_cpy(name2, sizeof(name2), name);
104 47582 : _gnutls_str_cat(name2, sizeof(name2),
105 : ".extnValue");
106 :
107 47582 : result =
108 47582 : _gnutls_x509_read_value(asn, name2, &value);
109 47582 : if (result < 0) {
110 5 : gnutls_assert();
111 5 : return result;
112 : }
113 :
114 47577 : ret->data = value.data;
115 47577 : ret->size = value.size;
116 :
117 47577 : if (_critical)
118 943 : *_critical = critical;
119 :
120 47577 : return 0;
121 : }
122 : }
123 : while (1);
124 :
125 51505 : if (result == ASN1_ELEMENT_NOT_FOUND) {
126 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
127 : } else {
128 0 : gnutls_assert();
129 0 : return _gnutls_asn2err(result);
130 : }
131 : }
132 :
133 : static int
134 4397 : get_indx_extension(ASN1_TYPE asn, const char *root,
135 : int indx, gnutls_datum_t * out)
136 : {
137 4397 : char name[MAX_NAME_SIZE];
138 4397 : int ret;
139 :
140 4397 : out->data = NULL;
141 4397 : out->size = 0;
142 :
143 4397 : snprintf(name, sizeof(name), "%s.?%u.extnValue", root, indx+1);
144 :
145 4397 : ret = _gnutls_x509_read_value(asn, name, out);
146 4397 : if (ret < 0)
147 8 : return gnutls_assert_val(ret);
148 :
149 : return 0;
150 : }
151 :
152 : int
153 98708 : _gnutls_x509_crt_get_extension(gnutls_x509_crt_t cert,
154 : const char *extension_id, int indx,
155 : gnutls_datum_t * data, unsigned int *critical)
156 : {
157 98708 : return _gnutls_get_extension(cert->cert, "tbsCertificate.extensions",
158 : extension_id, indx, data, critical);
159 : }
160 :
161 : /**
162 : * gnutls_x509_crt_get_extension_data2:
163 : * @cert: should contain a #gnutls_x509_crt_t type
164 : * @indx: Specifies which extension OID to read. Use (0) to get the first one.
165 : * @data: will contain the extension DER-encoded data
166 : *
167 : * This function will return the requested by the index extension data in the
168 : * certificate. The extension data will be allocated using
169 : * gnutls_malloc().
170 : *
171 : * Use gnutls_x509_crt_get_extension_info() to extract the OID.
172 : *
173 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
174 : * otherwise a negative error code is returned. If you have reached the
175 : * last extension available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
176 : * will be returned.
177 : **/
178 : int
179 4176 : gnutls_x509_crt_get_extension_data2(gnutls_x509_crt_t cert,
180 : unsigned indx,
181 : gnutls_datum_t * data)
182 : {
183 4176 : return get_indx_extension(cert->cert, "tbsCertificate.extensions",
184 : indx, data);
185 : }
186 :
187 : int
188 366 : _gnutls_x509_crl_get_extension(gnutls_x509_crl_t crl,
189 : const char *extension_id, int indx,
190 : gnutls_datum_t * data,
191 : unsigned int *critical)
192 : {
193 366 : return _gnutls_get_extension(crl->crl, "tbsCertList.crlExtensions",
194 : extension_id, indx, data, critical);
195 : }
196 :
197 : /**
198 : * gnutls_x509_crl_get_extension_data2:
199 : * @crl: should contain a #gnutls_x509_crl_t type
200 : * @indx: Specifies which extension OID to read. Use (0) to get the first one.
201 : * @data: will contain the extension DER-encoded data
202 : *
203 : * This function will return the requested by the index extension data in the
204 : * certificate revocation list. The extension data will be allocated using
205 : * gnutls_malloc().
206 : *
207 : * Use gnutls_x509_crt_get_extension_info() to extract the OID.
208 : *
209 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
210 : * otherwise a negative error code is returned. If you have reached the
211 : * last extension available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
212 : * will be returned.
213 : **/
214 : int
215 221 : gnutls_x509_crl_get_extension_data2(gnutls_x509_crl_t crl,
216 : unsigned indx,
217 : gnutls_datum_t * data)
218 : {
219 221 : return get_indx_extension(crl->crl, "tbsCertList.crlExtensions",
220 : indx, data);
221 : }
222 :
223 : /* This function will attempt to return the requested extension OID found in
224 : * the given X509v3 certificate.
225 : *
226 : * If you have passed the last extension, GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will
227 : * be returned.
228 : */
229 0 : static int get_extension_oid(ASN1_TYPE asn, const char *root,
230 : unsigned indx, void *oid, size_t * sizeof_oid)
231 : {
232 0 : int k, result, len;
233 0 : char name[MAX_NAME_SIZE], name2[MAX_NAME_SIZE];
234 0 : char extnID[MAX_OID_SIZE];
235 0 : unsigned indx_counter = 0;
236 :
237 0 : k = 0;
238 0 : do {
239 0 : k++;
240 :
241 0 : snprintf(name, sizeof(name), "%s.?%u", root, k);
242 :
243 0 : _gnutls_str_cpy(name2, sizeof(name2), name);
244 0 : _gnutls_str_cat(name2, sizeof(name2), ".extnID");
245 :
246 0 : len = sizeof(extnID) - 1;
247 0 : result = asn1_read_value(asn, name2, extnID, &len);
248 :
249 0 : if (result == ASN1_ELEMENT_NOT_FOUND) {
250 0 : gnutls_assert();
251 0 : break;
252 0 : } else if (result != ASN1_SUCCESS) {
253 0 : gnutls_assert();
254 0 : return _gnutls_asn2err(result);
255 : }
256 :
257 : /* Handle Extension
258 : */
259 0 : if (indx == indx_counter++) {
260 0 : len = strlen(extnID) + 1;
261 :
262 0 : if (*sizeof_oid < (unsigned) len) {
263 0 : *sizeof_oid = len;
264 0 : gnutls_assert();
265 0 : return GNUTLS_E_SHORT_MEMORY_BUFFER;
266 : }
267 :
268 0 : memcpy(oid, extnID, len);
269 0 : *sizeof_oid = len - 1;
270 :
271 0 : return 0;
272 : }
273 :
274 :
275 : }
276 : while (1);
277 :
278 0 : if (result == ASN1_ELEMENT_NOT_FOUND) {
279 0 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
280 : } else {
281 : gnutls_assert();
282 : return _gnutls_asn2err(result);
283 : }
284 : }
285 :
286 : /* This function will attempt to return the requested extension OID found in
287 : * the given X509v3 certificate.
288 : *
289 : * If you have passed the last extension, GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will
290 : * be returned.
291 : */
292 : int
293 0 : _gnutls_x509_crt_get_extension_oid(gnutls_x509_crt_t cert,
294 : int indx, void *oid,
295 : size_t * sizeof_oid)
296 : {
297 0 : return get_extension_oid(cert->cert, "tbsCertificate.extensions",
298 : indx, oid, sizeof_oid);
299 : }
300 :
301 : int
302 0 : _gnutls_x509_crl_get_extension_oid(gnutls_x509_crl_t crl,
303 : int indx, void *oid,
304 : size_t * sizeof_oid)
305 : {
306 0 : return get_extension_oid(crl->crl, "tbsCertList.crlExtensions",
307 : indx, oid, sizeof_oid);
308 : }
309 :
310 : /* This function will attempt to set the requested extension in
311 : * the given X509v3 certificate.
312 : *
313 : * Critical will be either 0 or 1.
314 : */
315 : static int
316 609 : add_extension(ASN1_TYPE asn, const char *root, const char *extension_id,
317 : const gnutls_datum_t * ext_data, unsigned int critical)
318 : {
319 609 : int result;
320 609 : const char *str;
321 609 : char name[MAX_NAME_SIZE];
322 :
323 609 : snprintf(name, sizeof(name), "%s", root);
324 :
325 : /* Add a new extension in the list.
326 : */
327 609 : result = asn1_write_value(asn, name, "NEW", 1);
328 609 : if (result != ASN1_SUCCESS) {
329 0 : gnutls_assert();
330 0 : return _gnutls_asn2err(result);
331 : }
332 :
333 609 : if (root[0] != 0)
334 561 : snprintf(name, sizeof(name), "%s.?LAST.extnID", root);
335 : else
336 48 : snprintf(name, sizeof(name), "?LAST.extnID");
337 :
338 609 : result = asn1_write_value(asn, name, extension_id, 1);
339 609 : if (result != ASN1_SUCCESS) {
340 0 : gnutls_assert();
341 0 : return _gnutls_asn2err(result);
342 : }
343 :
344 609 : if (critical == 0)
345 : str = "FALSE";
346 : else
347 217 : str = "TRUE";
348 :
349 609 : if (root[0] != 0)
350 561 : snprintf(name, sizeof(name), "%s.?LAST.critical", root);
351 : else
352 48 : snprintf(name, sizeof(name), "?LAST.critical");
353 :
354 609 : result = asn1_write_value(asn, name, str, 1);
355 609 : if (result != ASN1_SUCCESS) {
356 0 : gnutls_assert();
357 0 : return _gnutls_asn2err(result);
358 : }
359 :
360 609 : if (root[0] != 0)
361 561 : snprintf(name, sizeof(name), "%s.?LAST.extnValue", root);
362 : else
363 48 : snprintf(name, sizeof(name), "?LAST.extnValue");
364 :
365 609 : result = _gnutls_x509_write_value(asn, name, ext_data);
366 609 : if (result < 0) {
367 0 : gnutls_assert();
368 0 : return result;
369 : }
370 :
371 : return 0;
372 : }
373 :
374 : /* Overwrite the given extension (using the index)
375 : * index here starts from one.
376 : */
377 : static int
378 396 : overwrite_extension(ASN1_TYPE asn, const char *root, unsigned int indx,
379 : const gnutls_datum_t * ext_data, unsigned int critical)
380 : {
381 396 : char name[MAX_NAME_SIZE], name2[MAX_NAME_SIZE];
382 396 : const char *str;
383 396 : int result;
384 :
385 396 : if (root[0] != 0)
386 380 : snprintf(name, sizeof(name), "%s.?%u", root, indx);
387 : else
388 16 : snprintf(name, sizeof(name), "?%u", indx);
389 :
390 396 : if (critical == 0)
391 : str = "FALSE";
392 : else
393 15 : str = "TRUE";
394 :
395 396 : _gnutls_str_cpy(name2, sizeof(name2), name);
396 396 : _gnutls_str_cat(name2, sizeof(name2), ".critical");
397 :
398 396 : result = asn1_write_value(asn, name2, str, 1);
399 396 : if (result != ASN1_SUCCESS) {
400 0 : gnutls_assert();
401 0 : return _gnutls_asn2err(result);
402 : }
403 :
404 396 : _gnutls_str_cpy(name2, sizeof(name2), name);
405 396 : _gnutls_str_cat(name2, sizeof(name2), ".extnValue");
406 :
407 396 : result = _gnutls_x509_write_value(asn, name2, ext_data);
408 396 : if (result < 0) {
409 0 : gnutls_assert();
410 0 : return result;
411 : }
412 :
413 : return 0;
414 : }
415 :
416 : int
417 1005 : _gnutls_set_extension(ASN1_TYPE asn, const char *root,
418 : const char *ext_id,
419 : const gnutls_datum_t * ext_data, unsigned int critical)
420 : {
421 1005 : int result = 0;
422 1005 : int k, len;
423 1005 : char name[MAX_NAME_SIZE], name2[MAX_NAME_SIZE];
424 1005 : char extnID[MAX_OID_SIZE];
425 :
426 : /* Find the index of the given extension.
427 : */
428 1005 : k = 0;
429 3323 : do {
430 3323 : k++;
431 :
432 3323 : if (root[0] != 0)
433 3085 : snprintf(name, sizeof(name), "%s.?%u", root, k);
434 : else
435 238 : snprintf(name, sizeof(name), "?%u", k);
436 :
437 3323 : len = sizeof(extnID) - 1;
438 3323 : result = asn1_read_value(asn, name, extnID, &len);
439 :
440 : /* move to next
441 : */
442 :
443 3323 : if (result == ASN1_ELEMENT_NOT_FOUND) {
444 : break;
445 : }
446 :
447 2714 : do {
448 :
449 2714 : _gnutls_str_cpy(name2, sizeof(name2), name);
450 2714 : _gnutls_str_cat(name2, sizeof(name2), ".extnID");
451 :
452 2714 : len = sizeof(extnID) - 1;
453 2714 : result = asn1_read_value(asn, name2, extnID, &len);
454 :
455 2714 : if (result == ASN1_ELEMENT_NOT_FOUND) {
456 0 : gnutls_assert();
457 : break;
458 2714 : } else if (result != ASN1_SUCCESS) {
459 0 : gnutls_assert();
460 0 : return _gnutls_asn2err(result);
461 : }
462 :
463 : /* Handle Extension
464 : */
465 2714 : if (strcmp(extnID, ext_id) == 0) {
466 : /* extension was found
467 : */
468 396 : return overwrite_extension(asn, root, k,
469 : ext_data,
470 : critical);
471 : }
472 :
473 :
474 : }
475 : while (0);
476 : }
477 : while (1);
478 :
479 609 : if (result == ASN1_ELEMENT_NOT_FOUND) {
480 609 : return add_extension(asn, root, ext_id, ext_data,
481 : critical);
482 : } else {
483 : gnutls_assert();
484 : return _gnutls_asn2err(result);
485 : }
486 :
487 :
488 : return 0;
489 : }
490 :
491 : /* This function will attempt to overwrite the requested extension with
492 : * the given one.
493 : *
494 : * Critical will be either 0 or 1.
495 : */
496 : int
497 916 : _gnutls_x509_crt_set_extension(gnutls_x509_crt_t cert,
498 : const char *ext_id,
499 : const gnutls_datum_t * ext_data,
500 : unsigned int critical)
501 : {
502 916 : MODIFIED(cert);
503 916 : cert->use_extensions = 1;
504 :
505 916 : return _gnutls_set_extension(cert->cert, "tbsCertificate.extensions",
506 : ext_id, ext_data, critical);
507 : }
508 :
509 : int
510 16 : _gnutls_x509_crl_set_extension(gnutls_x509_crl_t crl,
511 : const char *ext_id,
512 : const gnutls_datum_t * ext_data,
513 : unsigned int critical)
514 : {
515 16 : return _gnutls_set_extension(crl->crl, "tbsCertList.crlExtensions", ext_id,
516 : ext_data, critical);
517 : }
518 :
519 : int
520 64 : _gnutls_x509_crq_set_extension(gnutls_x509_crq_t crq,
521 : const char *ext_id,
522 : const gnutls_datum_t * ext_data,
523 : unsigned int critical)
524 : {
525 64 : unsigned char *extensions = NULL;
526 64 : size_t extensions_size = 0;
527 64 : gnutls_datum_t der;
528 64 : ASN1_TYPE c2;
529 64 : int result;
530 :
531 64 : result =
532 64 : gnutls_x509_crq_get_attribute_by_oid(crq,
533 : "1.2.840.113549.1.9.14",
534 : 0, NULL,
535 : &extensions_size);
536 64 : if (result == GNUTLS_E_SHORT_MEMORY_BUFFER) {
537 56 : extensions = gnutls_malloc(extensions_size);
538 56 : if (extensions == NULL) {
539 0 : gnutls_assert();
540 0 : return GNUTLS_E_MEMORY_ERROR;
541 : }
542 :
543 56 : result = gnutls_x509_crq_get_attribute_by_oid(crq,
544 : "1.2.840.113549.1.9.14",
545 : 0,
546 : extensions,
547 : &extensions_size);
548 : }
549 64 : if (result < 0) {
550 8 : if (result == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
551 8 : extensions_size = 0;
552 : } else {
553 0 : gnutls_assert();
554 0 : gnutls_free(extensions);
555 0 : return result;
556 : }
557 : }
558 :
559 64 : result =
560 64 : asn1_create_element(_gnutls_get_pkix(), "PKIX1.Extensions",
561 : &c2);
562 64 : if (result != ASN1_SUCCESS) {
563 0 : gnutls_assert();
564 0 : gnutls_free(extensions);
565 0 : return _gnutls_asn2err(result);
566 : }
567 :
568 64 : if (extensions_size > 0) {
569 56 : result =
570 56 : _asn1_strict_der_decode(&c2, extensions, extensions_size,
571 : NULL);
572 56 : gnutls_free(extensions);
573 56 : if (result != ASN1_SUCCESS) {
574 0 : gnutls_assert();
575 0 : asn1_delete_structure(&c2);
576 0 : return _gnutls_asn2err(result);
577 : }
578 : }
579 :
580 64 : result = _gnutls_set_extension(c2, "", ext_id, ext_data, critical);
581 64 : if (result < 0) {
582 0 : gnutls_assert();
583 0 : asn1_delete_structure(&c2);
584 0 : return result;
585 : }
586 :
587 64 : result = _gnutls_x509_der_encode(c2, "", &der, 0);
588 :
589 64 : asn1_delete_structure(&c2);
590 :
591 64 : if (result < 0) {
592 0 : gnutls_assert();
593 0 : return result;
594 : }
595 :
596 64 : result =
597 128 : gnutls_x509_crq_set_attribute_by_oid(crq,
598 : "1.2.840.113549.1.9.14",
599 64 : der.data, der.size);
600 64 : gnutls_free(der.data);
601 64 : if (result < 0) {
602 0 : gnutls_assert();
603 0 : return result;
604 : }
605 :
606 :
607 : return 0;
608 : }
609 :
610 : /* extract an INTEGER from the DER encoded extension
611 : */
612 : int
613 350 : _gnutls_x509_ext_extract_number(uint8_t * number,
614 : size_t * _nr_size,
615 : uint8_t * extnValue, int extnValueLen)
616 : {
617 350 : ASN1_TYPE ext = ASN1_TYPE_EMPTY;
618 350 : int result;
619 350 : int nr_size = *_nr_size;
620 :
621 : /* here it doesn't matter so much that we use CertificateSerialNumber. It is equal
622 : * to using INTEGER.
623 : */
624 350 : if ((result = asn1_create_element
625 : (_gnutls_get_pkix(), "PKIX1.CertificateSerialNumber",
626 : &ext)) != ASN1_SUCCESS) {
627 0 : gnutls_assert();
628 0 : return _gnutls_asn2err(result);
629 : }
630 :
631 350 : result = _asn1_strict_der_decode(&ext, extnValue, extnValueLen, NULL);
632 350 : if (result != ASN1_SUCCESS) {
633 0 : gnutls_assert();
634 0 : asn1_delete_structure(&ext);
635 0 : return _gnutls_asn2err(result);
636 : }
637 :
638 : /* the default value of cA is false.
639 : */
640 350 : result = asn1_read_value(ext, "", number, &nr_size);
641 350 : if (result != ASN1_SUCCESS)
642 0 : result = _gnutls_asn2err(result);
643 : else
644 : result = 0;
645 :
646 350 : *_nr_size = nr_size;
647 :
648 350 : asn1_delete_structure(&ext);
649 :
650 350 : return result;
651 : }
652 :
653 : /* generate an INTEGER in a DER encoded extension
654 : */
655 : int
656 525 : _gnutls_x509_ext_gen_number(const uint8_t * number, size_t nr_size,
657 : gnutls_datum_t * der_ext)
658 : {
659 525 : ASN1_TYPE ext = ASN1_TYPE_EMPTY;
660 525 : int result;
661 :
662 525 : result =
663 525 : asn1_create_element(_gnutls_get_pkix(),
664 : "PKIX1.CertificateSerialNumber", &ext);
665 525 : if (result != ASN1_SUCCESS) {
666 0 : gnutls_assert();
667 0 : return _gnutls_asn2err(result);
668 : }
669 :
670 525 : result = asn1_write_value(ext, "", number, nr_size);
671 525 : if (result != ASN1_SUCCESS) {
672 0 : gnutls_assert();
673 0 : asn1_delete_structure(&ext);
674 0 : return _gnutls_asn2err(result);
675 : }
676 :
677 525 : result = _gnutls_x509_der_encode(ext, "", der_ext, 0);
678 :
679 525 : asn1_delete_structure(&ext);
680 :
681 525 : if (result < 0) {
682 0 : gnutls_assert();
683 0 : return result;
684 : }
685 :
686 : return 0;
687 : }
688 :
689 : int
690 1474 : _gnutls_write_general_name(ASN1_TYPE ext, const char *ext_name,
691 : gnutls_x509_subject_alt_name_t type,
692 : const void *data, unsigned int data_size)
693 : {
694 1474 : const char *str;
695 1474 : int result;
696 1474 : char name[128];
697 :
698 1474 : if (data == NULL) {
699 1 : if (data_size == 0)
700 : data = (void*)"";
701 : else
702 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
703 : }
704 :
705 1474 : switch (type) {
706 : case GNUTLS_SAN_DNSNAME:
707 : str = "dNSName";
708 : break;
709 177 : case GNUTLS_SAN_RFC822NAME:
710 177 : str = "rfc822Name";
711 177 : break;
712 235 : case GNUTLS_SAN_URI:
713 235 : str = "uniformResourceIdentifier";
714 235 : break;
715 196 : case GNUTLS_SAN_IPADDRESS:
716 196 : str = "iPAddress";
717 196 : break;
718 3 : case GNUTLS_SAN_REGISTERED_ID:
719 3 : str = "registeredID";
720 3 : break;
721 0 : default:
722 0 : gnutls_assert();
723 : return GNUTLS_E_INTERNAL_ERROR;
724 : }
725 :
726 1474 : result = asn1_write_value(ext, ext_name, str, 1);
727 1474 : if (result != ASN1_SUCCESS) {
728 0 : gnutls_assert();
729 0 : return _gnutls_asn2err(result);
730 : }
731 :
732 1474 : snprintf(name, sizeof(name), "%s.%s", ext_name, str);
733 :
734 1474 : result = asn1_write_value(ext, name, data, data_size);
735 1474 : if (result != ASN1_SUCCESS) {
736 0 : gnutls_assert();
737 0 : asn1_delete_structure(&ext);
738 0 : return _gnutls_asn2err(result);
739 : }
740 :
741 : return 0;
742 : }
743 :
744 : int
745 1443 : _gnutls_write_new_general_name(ASN1_TYPE ext, const char *ext_name,
746 : gnutls_x509_subject_alt_name_t type,
747 : const void *data, unsigned int data_size)
748 : {
749 1443 : int result;
750 1443 : char name[128];
751 :
752 1443 : result = asn1_write_value(ext, ext_name, "NEW", 1);
753 1443 : if (result != ASN1_SUCCESS) {
754 0 : gnutls_assert();
755 0 : return _gnutls_asn2err(result);
756 : }
757 :
758 1443 : if (ext_name[0] == 0) { /* no dot */
759 1213 : _gnutls_str_cpy(name, sizeof(name), "?LAST");
760 : } else {
761 230 : _gnutls_str_cpy(name, sizeof(name), ext_name);
762 230 : _gnutls_str_cat(name, sizeof(name), ".?LAST");
763 : }
764 :
765 1443 : result = _gnutls_write_general_name(ext, name, type,
766 : data, data_size);
767 1443 : if (result < 0) {
768 0 : gnutls_assert();
769 0 : return result;
770 : }
771 :
772 : return 0;
773 : }
774 :
775 : int
776 63 : _gnutls_write_new_othername(ASN1_TYPE ext, const char *ext_name,
777 : const char *oid,
778 : const void *data, unsigned int data_size)
779 : {
780 63 : int result;
781 63 : char name[128];
782 63 : char name2[128];
783 :
784 63 : result = asn1_write_value(ext, ext_name, "NEW", 1);
785 63 : if (result != ASN1_SUCCESS) {
786 0 : gnutls_assert();
787 0 : return _gnutls_asn2err(result);
788 : }
789 :
790 63 : if (ext_name[0] == 0) { /* no dot */
791 63 : _gnutls_str_cpy(name, sizeof(name), "?LAST");
792 : } else {
793 0 : _gnutls_str_cpy(name, sizeof(name), ext_name);
794 0 : _gnutls_str_cat(name, sizeof(name), ".?LAST");
795 : }
796 :
797 63 : result = asn1_write_value(ext, name, "otherName", 1);
798 63 : if (result != ASN1_SUCCESS) {
799 0 : gnutls_assert();
800 0 : return _gnutls_asn2err(result);
801 : }
802 :
803 63 : snprintf(name2, sizeof(name2), "%s.otherName.type-id", name);
804 :
805 63 : result = asn1_write_value(ext, name2, oid, 1);
806 63 : if (result != ASN1_SUCCESS) {
807 0 : gnutls_assert();
808 0 : asn1_delete_structure(&ext);
809 0 : return _gnutls_asn2err(result);
810 : }
811 :
812 63 : snprintf(name2, sizeof(name2), "%s.otherName.value", name);
813 :
814 63 : result = asn1_write_value(ext, name2, data, data_size);
815 63 : if (result != ASN1_SUCCESS) {
816 0 : gnutls_assert();
817 0 : asn1_delete_structure(&ext);
818 0 : return _gnutls_asn2err(result);
819 : }
820 :
821 : return 0;
822 : }
823 :
824 : /* Convert the given name to GeneralNames in a DER encoded extension.
825 : * This is the same as subject alternative name.
826 : */
827 : int
828 376 : _gnutls_x509_ext_gen_subject_alt_name(gnutls_x509_subject_alt_name_t
829 : type,
830 : const char *othername_oid,
831 : const void *data,
832 : unsigned int data_size,
833 : const gnutls_datum_t * prev_der_ext,
834 : gnutls_datum_t * der_ext)
835 : {
836 376 : int ret;
837 376 : gnutls_subject_alt_names_t sans = NULL;
838 376 : gnutls_datum_t name;
839 :
840 376 : ret = gnutls_subject_alt_names_init(&sans);
841 376 : if (ret < 0) {
842 0 : gnutls_assert();
843 0 : return ret;
844 : }
845 :
846 376 : if (prev_der_ext && prev_der_ext->data != NULL &&
847 301 : prev_der_ext->size != 0) {
848 :
849 301 : ret = gnutls_x509_ext_import_subject_alt_names(prev_der_ext, sans, 0);
850 301 : if (ret < 0) {
851 0 : gnutls_assert();
852 0 : goto cleanup;
853 : }
854 : }
855 :
856 376 : name.data = (void*)data;
857 376 : name.size = data_size;
858 376 : ret = gnutls_subject_alt_names_set(sans, type, &name, othername_oid);
859 376 : if (ret < 0) {
860 3 : gnutls_assert();
861 3 : goto cleanup;
862 : }
863 :
864 373 : ret = gnutls_x509_ext_export_subject_alt_names(sans, der_ext);
865 373 : if (ret < 0) {
866 0 : gnutls_assert();
867 0 : goto cleanup;
868 : }
869 :
870 : ret = 0;
871 376 : cleanup:
872 376 : if (sans != NULL)
873 376 : gnutls_subject_alt_names_deinit(sans);
874 :
875 : return ret;
876 : }
877 :
878 : /* generate the AuthorityKeyID in a DER encoded extension
879 : */
880 : int
881 47 : _gnutls_x509_ext_gen_auth_key_id(const void *id, size_t id_size,
882 : gnutls_datum_t * der_ext)
883 : {
884 47 : gnutls_x509_aki_t aki;
885 47 : int ret;
886 47 : gnutls_datum_t l_id;
887 :
888 47 : ret = gnutls_x509_aki_init(&aki);
889 47 : if (ret < 0)
890 0 : return gnutls_assert_val(ret);
891 :
892 47 : l_id.data = (void*)id;
893 47 : l_id.size = id_size;
894 47 : ret = gnutls_x509_aki_set_id(aki, &l_id);
895 47 : if (ret < 0) {
896 0 : gnutls_assert();
897 0 : goto cleanup;
898 : }
899 :
900 47 : ret = gnutls_x509_ext_export_authority_key_id(aki, der_ext);
901 47 : if (ret < 0) {
902 0 : gnutls_assert();
903 0 : goto cleanup;
904 : }
905 :
906 : ret = 0;
907 :
908 47 : cleanup:
909 47 : gnutls_x509_aki_deinit(aki);
910 47 : return ret;
911 : }
|