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
_gnutls_get_extension(ASN1_TYPE asn,const char * root,const char * extension_id,int indx,gnutls_datum_t * ret,unsigned int * _critical)37 _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 	int k, result, len;
42 	char name[MAX_NAME_SIZE], name2[MAX_NAME_SIZE];
43 	char str_critical[10];
44 	int critical = 0;
45 	char extnID[MAX_OID_SIZE];
46 	gnutls_datum_t value;
47 	int indx_counter = 0;
48 
49 	ret->data = NULL;
50 	ret->size = 0;
51 
52 	k = 0;
53 	do {
54 		k++;
55 
56 		snprintf(name, sizeof(name), "%s.?%u", root, k);
57 
58 		_gnutls_str_cpy(name2, sizeof(name2), name);
59 		_gnutls_str_cat(name2, sizeof(name2), ".extnID");
60 
61 		len = sizeof(extnID) - 1;
62 		result = asn1_read_value(asn, name2, extnID, &len);
63 
64 		if (result == ASN1_ELEMENT_NOT_FOUND) {
65 			break;
66 		} else if (result != ASN1_SUCCESS) {
67 			gnutls_assert();
68 			return _gnutls_asn2err(result);
69 		}
70 
71 		/* Handle Extension
72 		 */
73 		if (strcmp(extnID, extension_id) == 0
74 		    && indx == indx_counter++) {
75 			/* extension was found
76 			 */
77 
78 			/* read the critical status.
79 			 */
80 			_gnutls_str_cpy(name2, sizeof(name2), name);
81 			_gnutls_str_cat(name2, sizeof(name2), ".critical");
82 
83 			len = sizeof(str_critical);
84 			result =
85 			    asn1_read_value(asn, name2,
86 					    str_critical, &len);
87 
88 			if (result == ASN1_ELEMENT_NOT_FOUND) {
89 				gnutls_assert();
90 				break;
91 			} else if (result != ASN1_SUCCESS) {
92 				gnutls_assert();
93 				return _gnutls_asn2err(result);
94 			}
95 
96 			if (str_critical[0] == 'T')
97 				critical = 1;
98 			else
99 				critical = 0;
100 
101 			/* read the value.
102 			 */
103 			_gnutls_str_cpy(name2, sizeof(name2), name);
104 			_gnutls_str_cat(name2, sizeof(name2),
105 					".extnValue");
106 
107 			result =
108 			    _gnutls_x509_read_value(asn, name2, &value);
109 			if (result < 0) {
110 				gnutls_assert();
111 				return result;
112 			}
113 
114 			ret->data = value.data;
115 			ret->size = value.size;
116 
117 			if (_critical)
118 				*_critical = critical;
119 
120 			return 0;
121 		}
122 	}
123 	while (1);
124 
125 	if (result == ASN1_ELEMENT_NOT_FOUND) {
126 		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
127 	} else {
128 		gnutls_assert();
129 		return _gnutls_asn2err(result);
130 	}
131 }
132 
133 static int
get_indx_extension(ASN1_TYPE asn,const char * root,int indx,gnutls_datum_t * out)134 get_indx_extension(ASN1_TYPE asn, const char *root,
135 	      int indx, gnutls_datum_t * out)
136 {
137 	char name[MAX_NAME_SIZE];
138 	int ret;
139 
140 	out->data = NULL;
141 	out->size = 0;
142 
143 	snprintf(name, sizeof(name), "%s.?%u.extnValue", root, indx+1);
144 
145 	ret = _gnutls_x509_read_value(asn, name, out);
146 	if (ret < 0)
147 		return gnutls_assert_val(ret);
148 
149 	return 0;
150 }
151 
152 int
_gnutls_x509_crt_get_extension(gnutls_x509_crt_t cert,const char * extension_id,int indx,gnutls_datum_t * data,unsigned int * critical)153 _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 	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
gnutls_x509_crt_get_extension_data2(gnutls_x509_crt_t cert,unsigned indx,gnutls_datum_t * data)179 gnutls_x509_crt_get_extension_data2(gnutls_x509_crt_t cert,
180 			       unsigned indx,
181 			       gnutls_datum_t * data)
182 {
183 	return get_indx_extension(cert->cert, "tbsCertificate.extensions",
184 			     indx, data);
185 }
186 
187 int
_gnutls_x509_crl_get_extension(gnutls_x509_crl_t crl,const char * extension_id,int indx,gnutls_datum_t * data,unsigned int * critical)188 _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 	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
gnutls_x509_crl_get_extension_data2(gnutls_x509_crl_t crl,unsigned indx,gnutls_datum_t * data)215 gnutls_x509_crl_get_extension_data2(gnutls_x509_crl_t crl,
216 			       unsigned indx,
217 			       gnutls_datum_t * data)
218 {
219 	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  */
get_extension_oid(ASN1_TYPE asn,const char * root,unsigned indx,void * oid,size_t * sizeof_oid)229 static int get_extension_oid(ASN1_TYPE asn, const char *root,
230 		  unsigned indx, void *oid, size_t * sizeof_oid)
231 {
232 	int k, result, len;
233 	char name[MAX_NAME_SIZE], name2[MAX_NAME_SIZE];
234 	char extnID[MAX_OID_SIZE];
235 	unsigned indx_counter = 0;
236 
237 	k = 0;
238 	do {
239 		k++;
240 
241 		snprintf(name, sizeof(name), "%s.?%u", root, k);
242 
243 		_gnutls_str_cpy(name2, sizeof(name2), name);
244 		_gnutls_str_cat(name2, sizeof(name2), ".extnID");
245 
246 		len = sizeof(extnID) - 1;
247 		result = asn1_read_value(asn, name2, extnID, &len);
248 
249 		if (result == ASN1_ELEMENT_NOT_FOUND) {
250 			gnutls_assert();
251 			break;
252 		} else if (result != ASN1_SUCCESS) {
253 			gnutls_assert();
254 			return _gnutls_asn2err(result);
255 		}
256 
257 		/* Handle Extension
258 		 */
259 		if (indx == indx_counter++) {
260 			len = strlen(extnID) + 1;
261 
262 			if (*sizeof_oid < (unsigned) len) {
263 				*sizeof_oid = len;
264 				gnutls_assert();
265 				return GNUTLS_E_SHORT_MEMORY_BUFFER;
266 			}
267 
268 			memcpy(oid, extnID, len);
269 			*sizeof_oid = len - 1;
270 
271 			return 0;
272 		}
273 
274 
275 	}
276 	while (1);
277 
278 	if (result == ASN1_ELEMENT_NOT_FOUND) {
279 		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
_gnutls_x509_crt_get_extension_oid(gnutls_x509_crt_t cert,int indx,void * oid,size_t * sizeof_oid)293 _gnutls_x509_crt_get_extension_oid(gnutls_x509_crt_t cert,
294 				   int indx, void *oid,
295 				   size_t * sizeof_oid)
296 {
297 	return get_extension_oid(cert->cert, "tbsCertificate.extensions",
298 				 indx, oid, sizeof_oid);
299 }
300 
301 int
_gnutls_x509_crl_get_extension_oid(gnutls_x509_crl_t crl,int indx,void * oid,size_t * sizeof_oid)302 _gnutls_x509_crl_get_extension_oid(gnutls_x509_crl_t crl,
303 				   int indx, void *oid,
304 				   size_t * sizeof_oid)
305 {
306 	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
add_extension(ASN1_TYPE asn,const char * root,const char * extension_id,const gnutls_datum_t * ext_data,unsigned int critical)316 add_extension(ASN1_TYPE asn, const char *root, const char *extension_id,
317 	      const gnutls_datum_t * ext_data, unsigned int critical)
318 {
319 	int result;
320 	const char *str;
321 	char name[MAX_NAME_SIZE];
322 
323 	snprintf(name, sizeof(name), "%s", root);
324 
325 	/* Add a new extension in the list.
326 	 */
327 	result = asn1_write_value(asn, name, "NEW", 1);
328 	if (result != ASN1_SUCCESS) {
329 		gnutls_assert();
330 		return _gnutls_asn2err(result);
331 	}
332 
333 	if (root[0] != 0)
334 		snprintf(name, sizeof(name), "%s.?LAST.extnID", root);
335 	else
336 		snprintf(name, sizeof(name), "?LAST.extnID");
337 
338 	result = asn1_write_value(asn, name, extension_id, 1);
339 	if (result != ASN1_SUCCESS) {
340 		gnutls_assert();
341 		return _gnutls_asn2err(result);
342 	}
343 
344 	if (critical == 0)
345 		str = "FALSE";
346 	else
347 		str = "TRUE";
348 
349 	if (root[0] != 0)
350 		snprintf(name, sizeof(name), "%s.?LAST.critical", root);
351 	else
352 		snprintf(name, sizeof(name), "?LAST.critical");
353 
354 	result = asn1_write_value(asn, name, str, 1);
355 	if (result != ASN1_SUCCESS) {
356 		gnutls_assert();
357 		return _gnutls_asn2err(result);
358 	}
359 
360 	if (root[0] != 0)
361 		snprintf(name, sizeof(name), "%s.?LAST.extnValue", root);
362 	else
363 		snprintf(name, sizeof(name), "?LAST.extnValue");
364 
365 	result = _gnutls_x509_write_value(asn, name, ext_data);
366 	if (result < 0) {
367 		gnutls_assert();
368 		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
overwrite_extension(ASN1_TYPE asn,const char * root,unsigned int indx,const gnutls_datum_t * ext_data,unsigned int critical)378 overwrite_extension(ASN1_TYPE asn, const char *root, unsigned int indx,
379 		    const gnutls_datum_t * ext_data, unsigned int critical)
380 {
381 	char name[MAX_NAME_SIZE], name2[MAX_NAME_SIZE];
382 	const char *str;
383 	int result;
384 
385 	if (root[0] != 0)
386 		snprintf(name, sizeof(name), "%s.?%u", root, indx);
387 	else
388 		snprintf(name, sizeof(name), "?%u", indx);
389 
390 	if (critical == 0)
391 		str = "FALSE";
392 	else
393 		str = "TRUE";
394 
395 	_gnutls_str_cpy(name2, sizeof(name2), name);
396 	_gnutls_str_cat(name2, sizeof(name2), ".critical");
397 
398 	result = asn1_write_value(asn, name2, str, 1);
399 	if (result != ASN1_SUCCESS) {
400 		gnutls_assert();
401 		return _gnutls_asn2err(result);
402 	}
403 
404 	_gnutls_str_cpy(name2, sizeof(name2), name);
405 	_gnutls_str_cat(name2, sizeof(name2), ".extnValue");
406 
407 	result = _gnutls_x509_write_value(asn, name2, ext_data);
408 	if (result < 0) {
409 		gnutls_assert();
410 		return result;
411 	}
412 
413 	return 0;
414 }
415 
416 int
_gnutls_set_extension(ASN1_TYPE asn,const char * root,const char * ext_id,const gnutls_datum_t * ext_data,unsigned int critical)417 _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 	int result = 0;
422 	int k, len;
423 	char name[MAX_NAME_SIZE], name2[MAX_NAME_SIZE];
424 	char extnID[MAX_OID_SIZE];
425 
426 	/* Find the index of the given extension.
427 	 */
428 	k = 0;
429 	do {
430 		k++;
431 
432 		if (root[0] != 0)
433 			snprintf(name, sizeof(name), "%s.?%u", root, k);
434 		else
435 			snprintf(name, sizeof(name), "?%u", k);
436 
437 		len = sizeof(extnID) - 1;
438 		result = asn1_read_value(asn, name, extnID, &len);
439 
440 		/* move to next
441 		 */
442 
443 		if (result == ASN1_ELEMENT_NOT_FOUND) {
444 			break;
445 		}
446 
447 		do {
448 
449 			_gnutls_str_cpy(name2, sizeof(name2), name);
450 			_gnutls_str_cat(name2, sizeof(name2), ".extnID");
451 
452 			len = sizeof(extnID) - 1;
453 			result = asn1_read_value(asn, name2, extnID, &len);
454 
455 			if (result == ASN1_ELEMENT_NOT_FOUND) {
456 				gnutls_assert();
457 				break;
458 			} else if (result != ASN1_SUCCESS) {
459 				gnutls_assert();
460 				return _gnutls_asn2err(result);
461 			}
462 
463 			/* Handle Extension
464 			 */
465 			if (strcmp(extnID, ext_id) == 0) {
466 				/* extension was found
467 				 */
468 				return overwrite_extension(asn, root, k,
469 							   ext_data,
470 							   critical);
471 			}
472 
473 
474 		}
475 		while (0);
476 	}
477 	while (1);
478 
479 	if (result == ASN1_ELEMENT_NOT_FOUND) {
480 		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
_gnutls_x509_crt_set_extension(gnutls_x509_crt_t cert,const char * ext_id,const gnutls_datum_t * ext_data,unsigned int critical)497 _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 	MODIFIED(cert);
503 	cert->use_extensions = 1;
504 
505 	return _gnutls_set_extension(cert->cert, "tbsCertificate.extensions",
506 			     ext_id, ext_data, critical);
507 }
508 
509 int
_gnutls_x509_crl_set_extension(gnutls_x509_crl_t crl,const char * ext_id,const gnutls_datum_t * ext_data,unsigned int critical)510 _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 	return _gnutls_set_extension(crl->crl, "tbsCertList.crlExtensions", ext_id,
516 			     ext_data, critical);
517 }
518 
519 int
_gnutls_x509_crq_set_extension(gnutls_x509_crq_t crq,const char * ext_id,const gnutls_datum_t * ext_data,unsigned int critical)520 _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 	unsigned char *extensions = NULL;
526 	size_t extensions_size = 0;
527 	gnutls_datum_t der;
528 	ASN1_TYPE c2;
529 	int result;
530 
531 	result =
532 	    gnutls_x509_crq_get_attribute_by_oid(crq,
533 						 "1.2.840.113549.1.9.14",
534 						 0, NULL,
535 						 &extensions_size);
536 	if (result == GNUTLS_E_SHORT_MEMORY_BUFFER) {
537 		extensions = gnutls_malloc(extensions_size);
538 		if (extensions == NULL) {
539 			gnutls_assert();
540 			return GNUTLS_E_MEMORY_ERROR;
541 		}
542 
543 		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 	if (result < 0) {
550 		if (result == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
551 			extensions_size = 0;
552 		} else {
553 			gnutls_assert();
554 			gnutls_free(extensions);
555 			return result;
556 		}
557 	}
558 
559 	result =
560 	    asn1_create_element(_gnutls_get_pkix(), "PKIX1.Extensions",
561 				&c2);
562 	if (result != ASN1_SUCCESS) {
563 		gnutls_assert();
564 		gnutls_free(extensions);
565 		return _gnutls_asn2err(result);
566 	}
567 
568 	if (extensions_size > 0) {
569 		result =
570 		    _asn1_strict_der_decode(&c2, extensions, extensions_size,
571 				      NULL);
572 		gnutls_free(extensions);
573 		if (result != ASN1_SUCCESS) {
574 			gnutls_assert();
575 			asn1_delete_structure(&c2);
576 			return _gnutls_asn2err(result);
577 		}
578 	}
579 
580 	result = _gnutls_set_extension(c2, "", ext_id, ext_data, critical);
581 	if (result < 0) {
582 		gnutls_assert();
583 		asn1_delete_structure(&c2);
584 		return result;
585 	}
586 
587 	result = _gnutls_x509_der_encode(c2, "", &der, 0);
588 
589 	asn1_delete_structure(&c2);
590 
591 	if (result < 0) {
592 		gnutls_assert();
593 		return result;
594 	}
595 
596 	result =
597 	    gnutls_x509_crq_set_attribute_by_oid(crq,
598 						 "1.2.840.113549.1.9.14",
599 						 der.data, der.size);
600 	gnutls_free(der.data);
601 	if (result < 0) {
602 		gnutls_assert();
603 		return result;
604 	}
605 
606 
607 	return 0;
608 }
609 
610 /* extract an INTEGER from the DER encoded extension
611  */
612 int
_gnutls_x509_ext_extract_number(uint8_t * number,size_t * _nr_size,uint8_t * extnValue,int extnValueLen)613 _gnutls_x509_ext_extract_number(uint8_t * number,
614 				size_t * _nr_size,
615 				uint8_t * extnValue, int extnValueLen)
616 {
617 	ASN1_TYPE ext = ASN1_TYPE_EMPTY;
618 	int result;
619 	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 	if ((result = asn1_create_element
625 	     (_gnutls_get_pkix(), "PKIX1.CertificateSerialNumber",
626 	      &ext)) != ASN1_SUCCESS) {
627 		gnutls_assert();
628 		return _gnutls_asn2err(result);
629 	}
630 
631 	result = _asn1_strict_der_decode(&ext, extnValue, extnValueLen, NULL);
632 	if (result != ASN1_SUCCESS) {
633 		gnutls_assert();
634 		asn1_delete_structure(&ext);
635 		return _gnutls_asn2err(result);
636 	}
637 
638 	/* the default value of cA is false.
639 	 */
640 	result = asn1_read_value(ext, "", number, &nr_size);
641 	if (result != ASN1_SUCCESS)
642 		result = _gnutls_asn2err(result);
643 	else
644 		result = 0;
645 
646 	*_nr_size = nr_size;
647 
648 	asn1_delete_structure(&ext);
649 
650 	return result;
651 }
652 
653 /* generate an INTEGER in a DER encoded extension
654  */
655 int
_gnutls_x509_ext_gen_number(const uint8_t * number,size_t nr_size,gnutls_datum_t * der_ext)656 _gnutls_x509_ext_gen_number(const uint8_t * number, size_t nr_size,
657 			    gnutls_datum_t * der_ext)
658 {
659 	ASN1_TYPE ext = ASN1_TYPE_EMPTY;
660 	int result;
661 
662 	result =
663 	    asn1_create_element(_gnutls_get_pkix(),
664 				"PKIX1.CertificateSerialNumber", &ext);
665 	if (result != ASN1_SUCCESS) {
666 		gnutls_assert();
667 		return _gnutls_asn2err(result);
668 	}
669 
670 	result = asn1_write_value(ext, "", number, nr_size);
671 	if (result != ASN1_SUCCESS) {
672 		gnutls_assert();
673 		asn1_delete_structure(&ext);
674 		return _gnutls_asn2err(result);
675 	}
676 
677 	result = _gnutls_x509_der_encode(ext, "", der_ext, 0);
678 
679 	asn1_delete_structure(&ext);
680 
681 	if (result < 0) {
682 		gnutls_assert();
683 		return result;
684 	}
685 
686 	return 0;
687 }
688 
689 int
_gnutls_write_general_name(ASN1_TYPE ext,const char * ext_name,gnutls_x509_subject_alt_name_t type,const void * data,unsigned int data_size)690 _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 	const char *str;
695 	int result;
696 	char name[128];
697 
698 	if (data == NULL) {
699 		if (data_size == 0)
700 			data = (void*)"";
701 		else
702 			return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
703 	}
704 
705 	switch (type) {
706 	case GNUTLS_SAN_DNSNAME:
707 		str = "dNSName";
708 		break;
709 	case GNUTLS_SAN_RFC822NAME:
710 		str = "rfc822Name";
711 		break;
712 	case GNUTLS_SAN_URI:
713 		str = "uniformResourceIdentifier";
714 		break;
715 	case GNUTLS_SAN_IPADDRESS:
716 		str = "iPAddress";
717 		break;
718 	case GNUTLS_SAN_REGISTERED_ID:
719 		str = "registeredID";
720 		break;
721 	default:
722 		gnutls_assert();
723 		return GNUTLS_E_INTERNAL_ERROR;
724 	}
725 
726 	result = asn1_write_value(ext, ext_name, str, 1);
727 	if (result != ASN1_SUCCESS) {
728 		gnutls_assert();
729 		return _gnutls_asn2err(result);
730 	}
731 
732 	snprintf(name, sizeof(name), "%s.%s", ext_name, str);
733 
734 	result = asn1_write_value(ext, name, data, data_size);
735 	if (result != ASN1_SUCCESS) {
736 		gnutls_assert();
737 		asn1_delete_structure(&ext);
738 		return _gnutls_asn2err(result);
739 	}
740 
741 	return 0;
742 }
743 
744 int
_gnutls_write_new_general_name(ASN1_TYPE ext,const char * ext_name,gnutls_x509_subject_alt_name_t type,const void * data,unsigned int data_size)745 _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 	int result;
750 	char name[128];
751 
752 	result = asn1_write_value(ext, ext_name, "NEW", 1);
753 	if (result != ASN1_SUCCESS) {
754 		gnutls_assert();
755 		return _gnutls_asn2err(result);
756 	}
757 
758 	if (ext_name[0] == 0) {	/* no dot */
759 		_gnutls_str_cpy(name, sizeof(name), "?LAST");
760 	} else {
761 		_gnutls_str_cpy(name, sizeof(name), ext_name);
762 		_gnutls_str_cat(name, sizeof(name), ".?LAST");
763 	}
764 
765 	result = _gnutls_write_general_name(ext, name, type,
766 		data, data_size);
767 	if (result < 0) {
768 		gnutls_assert();
769 		return result;
770 	}
771 
772 	return 0;
773 }
774 
775 int
_gnutls_write_new_othername(ASN1_TYPE ext,const char * ext_name,const char * oid,const void * data,unsigned int data_size)776 _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 	int result;
781 	char name[128];
782 	char name2[128];
783 
784 	result = asn1_write_value(ext, ext_name, "NEW", 1);
785 	if (result != ASN1_SUCCESS) {
786 		gnutls_assert();
787 		return _gnutls_asn2err(result);
788 	}
789 
790 	if (ext_name[0] == 0) {	/* no dot */
791 		_gnutls_str_cpy(name, sizeof(name), "?LAST");
792 	} else {
793 		_gnutls_str_cpy(name, sizeof(name), ext_name);
794 		_gnutls_str_cat(name, sizeof(name), ".?LAST");
795 	}
796 
797 	result = asn1_write_value(ext, name, "otherName", 1);
798 	if (result != ASN1_SUCCESS) {
799 		gnutls_assert();
800 		return _gnutls_asn2err(result);
801 	}
802 
803 	snprintf(name2, sizeof(name2), "%s.otherName.type-id", name);
804 
805 	result = asn1_write_value(ext, name2, oid, 1);
806 	if (result != ASN1_SUCCESS) {
807 		gnutls_assert();
808 		asn1_delete_structure(&ext);
809 		return _gnutls_asn2err(result);
810 	}
811 
812 	snprintf(name2, sizeof(name2), "%s.otherName.value", name);
813 
814 	result = asn1_write_value(ext, name2, data, data_size);
815 	if (result != ASN1_SUCCESS) {
816 		gnutls_assert();
817 		asn1_delete_structure(&ext);
818 		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
_gnutls_x509_ext_gen_subject_alt_name(gnutls_x509_subject_alt_name_t type,const char * othername_oid,const void * data,unsigned int data_size,const gnutls_datum_t * prev_der_ext,gnutls_datum_t * der_ext)828 _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 	int ret;
837 	gnutls_subject_alt_names_t sans = NULL;
838 	gnutls_datum_t name;
839 
840 	ret = gnutls_subject_alt_names_init(&sans);
841 	if (ret < 0) {
842 		gnutls_assert();
843 		return ret;
844 	}
845 
846 	if (prev_der_ext && prev_der_ext->data != NULL &&
847 		prev_der_ext->size != 0) {
848 
849 		ret = gnutls_x509_ext_import_subject_alt_names(prev_der_ext, sans, 0);
850 		if (ret < 0) {
851 			gnutls_assert();
852 			goto cleanup;
853 		}
854 	}
855 
856 	name.data = (void*)data;
857 	name.size = data_size;
858 	ret = gnutls_subject_alt_names_set(sans, type, &name, othername_oid);
859 	if (ret < 0) {
860 		gnutls_assert();
861 		goto cleanup;
862 	}
863 
864 	ret = gnutls_x509_ext_export_subject_alt_names(sans, der_ext);
865 	if (ret < 0) {
866 		gnutls_assert();
867 		goto cleanup;
868 	}
869 
870 	ret = 0;
871 cleanup:
872 	if (sans != NULL)
873 		gnutls_subject_alt_names_deinit(sans);
874 
875 	return ret;
876 }
877 
878 /* generate the AuthorityKeyID in a DER encoded extension
879  */
880 int
_gnutls_x509_ext_gen_auth_key_id(const void * id,size_t id_size,gnutls_datum_t * der_ext)881 _gnutls_x509_ext_gen_auth_key_id(const void *id, size_t id_size,
882 				 gnutls_datum_t * der_ext)
883 {
884 	gnutls_x509_aki_t aki;
885 	int ret;
886 	gnutls_datum_t l_id;
887 
888 	ret = gnutls_x509_aki_init(&aki);
889 	if (ret < 0)
890 		return gnutls_assert_val(ret);
891 
892 	l_id.data = (void*)id;
893 	l_id.size = id_size;
894 	ret = gnutls_x509_aki_set_id(aki, &l_id);
895 	if (ret < 0) {
896 		gnutls_assert();
897 		goto cleanup;
898 	}
899 
900 	ret = gnutls_x509_ext_export_authority_key_id(aki, der_ext);
901 	if (ret < 0) {
902 		gnutls_assert();
903 		goto cleanup;
904 	}
905 
906 	ret = 0;
907 
908  cleanup:
909 	gnutls_x509_aki_deinit(aki);
910 	return ret;
911 }
912