/src/gnutls/lib/x509/x509_write.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2003-2016 Free Software Foundation, Inc. |
3 | | * Copyright (C) 2016-2017 Red Hat, Inc. |
4 | | * |
5 | | * Author: Nikos Mavrogiannopoulos |
6 | | * |
7 | | * This file is part of GnuTLS. |
8 | | * |
9 | | * The GnuTLS is free software; you can redistribute it and/or |
10 | | * modify it under the terms of the GNU Lesser General Public License |
11 | | * as published by the Free Software Foundation; either version 2.1 of |
12 | | * the License, or (at your option) any later version. |
13 | | * |
14 | | * This library is distributed in the hope that it will be useful, but |
15 | | * WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
17 | | * Lesser General Public License for more details. |
18 | | * |
19 | | * You should have received a copy of the GNU Lesser General Public License |
20 | | * along with this program. If not, see <https://www.gnu.org/licenses/> |
21 | | * |
22 | | */ |
23 | | |
24 | | /* This file contains functions to handle X.509 certificate generation. |
25 | | */ |
26 | | |
27 | | #include "gnutls_int.h" |
28 | | |
29 | | #include <datum.h> |
30 | | #include <global.h> |
31 | | #include "errors.h" |
32 | | #include <common.h> |
33 | | #include <x509.h> |
34 | | #include <gnutls/x509-ext.h> |
35 | | #include <x509_b64.h> |
36 | | #include "x509_int.h" |
37 | | #include <libtasn1.h> |
38 | | #include <pk.h> |
39 | | |
40 | | static void disable_optional_stuff(gnutls_x509_crt_t cert); |
41 | | |
42 | | /** |
43 | | * gnutls_x509_crt_set_dn_by_oid: |
44 | | * @crt: a certificate of type #gnutls_x509_crt_t |
45 | | * @oid: holds an Object Identifier in a null terminated string |
46 | | * @raw_flag: must be 0, or 1 if the data are DER encoded |
47 | | * @name: a pointer to the name |
48 | | * @sizeof_name: holds the size of @name |
49 | | * |
50 | | * This function will set the part of the name of the Certificate |
51 | | * subject, specified by the given OID. The input string should be |
52 | | * ASCII or UTF-8 encoded. |
53 | | * |
54 | | * Some helper macros with popular OIDs can be found in gnutls/x509.h |
55 | | * With this function you can only set the known OIDs. You can test |
56 | | * for known OIDs using gnutls_x509_dn_oid_known(). For OIDs that are |
57 | | * not known (by gnutls) you should properly DER encode your data, |
58 | | * and call this function with @raw_flag set. |
59 | | * |
60 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
61 | | * negative error value. |
62 | | **/ |
63 | | int |
64 | | gnutls_x509_crt_set_dn_by_oid(gnutls_x509_crt_t crt, const char *oid, |
65 | | unsigned int raw_flag, const void *name, |
66 | | unsigned int sizeof_name) |
67 | 0 | { |
68 | 0 | if (sizeof_name == 0 || name == NULL || crt == NULL) { |
69 | 0 | return GNUTLS_E_INVALID_REQUEST; |
70 | 0 | } |
71 | | |
72 | 0 | MODIFIED(crt); |
73 | |
|
74 | 0 | return _gnutls_x509_set_dn_oid(crt->cert, "tbsCertificate.subject", |
75 | 0 | oid, raw_flag, name, sizeof_name); |
76 | 0 | } |
77 | | |
78 | | /** |
79 | | * gnutls_x509_crt_set_issuer_dn_by_oid: |
80 | | * @crt: a certificate of type #gnutls_x509_crt_t |
81 | | * @oid: holds an Object Identifier in a null terminated string |
82 | | * @raw_flag: must be 0, or 1 if the data are DER encoded |
83 | | * @name: a pointer to the name |
84 | | * @sizeof_name: holds the size of @name |
85 | | * |
86 | | * This function will set the part of the name of the Certificate |
87 | | * issuer, specified by the given OID. The input string should be |
88 | | * ASCII or UTF-8 encoded. |
89 | | * |
90 | | * Some helper macros with popular OIDs can be found in gnutls/x509.h |
91 | | * With this function you can only set the known OIDs. You can test |
92 | | * for known OIDs using gnutls_x509_dn_oid_known(). For OIDs that are |
93 | | * not known (by gnutls) you should properly DER encode your data, |
94 | | * and call this function with @raw_flag set. |
95 | | * |
96 | | * Normally you do not need to call this function, since the signing |
97 | | * operation will copy the signer's name as the issuer of the |
98 | | * certificate. |
99 | | * |
100 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
101 | | * negative error value. |
102 | | **/ |
103 | | int |
104 | | gnutls_x509_crt_set_issuer_dn_by_oid(gnutls_x509_crt_t crt, |
105 | | const char *oid, |
106 | | unsigned int raw_flag, |
107 | | const void *name, unsigned int sizeof_name) |
108 | 0 | { |
109 | 0 | if (sizeof_name == 0 || name == NULL || crt == NULL) { |
110 | 0 | return GNUTLS_E_INVALID_REQUEST; |
111 | 0 | } |
112 | | |
113 | 0 | MODIFIED(crt); |
114 | |
|
115 | 0 | return _gnutls_x509_set_dn_oid(crt->cert, "tbsCertificate.issuer", |
116 | 0 | oid, raw_flag, name, sizeof_name); |
117 | 0 | } |
118 | | |
119 | | /** |
120 | | * gnutls_x509_crt_set_proxy_dn: |
121 | | * @crt: a gnutls_x509_crt_t type with the new proxy cert |
122 | | * @eecrt: the end entity certificate that will be issuing the proxy |
123 | | * @raw_flag: must be 0, or 1 if the CN is DER encoded |
124 | | * @name: a pointer to the CN name, may be NULL (but MUST then be added later) |
125 | | * @sizeof_name: holds the size of @name |
126 | | * |
127 | | * This function will set the subject in @crt to the end entity's |
128 | | * @eecrt subject name, and add a single Common Name component @name |
129 | | * of size @sizeof_name. This corresponds to the required proxy |
130 | | * certificate naming style. Note that if @name is %NULL, you MUST |
131 | | * set it later by using gnutls_x509_crt_set_dn_by_oid() or similar. |
132 | | * |
133 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
134 | | * negative error value. |
135 | | **/ |
136 | | int |
137 | | gnutls_x509_crt_set_proxy_dn(gnutls_x509_crt_t crt, |
138 | | gnutls_x509_crt_t eecrt, |
139 | | unsigned int raw_flag, const void *name, |
140 | | unsigned int sizeof_name) |
141 | 0 | { |
142 | 0 | int result; |
143 | |
|
144 | 0 | if (crt == NULL || eecrt == NULL) { |
145 | 0 | return GNUTLS_E_INVALID_REQUEST; |
146 | 0 | } |
147 | | |
148 | 0 | MODIFIED(crt); |
149 | |
|
150 | 0 | result = asn1_copy_node(crt->cert, "tbsCertificate.subject", |
151 | 0 | eecrt->cert, "tbsCertificate.subject"); |
152 | 0 | if (result != ASN1_SUCCESS) { |
153 | 0 | gnutls_assert(); |
154 | 0 | return _gnutls_asn2err(result); |
155 | 0 | } |
156 | | |
157 | 0 | if (name && sizeof_name) { |
158 | 0 | return _gnutls_x509_set_dn_oid(crt->cert, |
159 | 0 | "tbsCertificate.subject", |
160 | 0 | GNUTLS_OID_X520_COMMON_NAME, |
161 | 0 | raw_flag, name, sizeof_name); |
162 | 0 | } |
163 | | |
164 | 0 | return 0; |
165 | 0 | } |
166 | | |
167 | | /** |
168 | | * gnutls_x509_crt_set_version: |
169 | | * @crt: a certificate of type #gnutls_x509_crt_t |
170 | | * @version: holds the version number. For X.509v1 certificates must be 1. |
171 | | * |
172 | | * This function will set the version of the certificate. This must |
173 | | * be one for X.509 version 1, and so on. Plain certificates without |
174 | | * extensions must have version set to one. |
175 | | * |
176 | | * To create well-formed certificates, you must specify version 3 if |
177 | | * you use any certificate extensions. Extensions are created by |
178 | | * functions such as gnutls_x509_crt_set_subject_alt_name() |
179 | | * or gnutls_x509_crt_set_key_usage(). |
180 | | * |
181 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
182 | | * negative error value. |
183 | | **/ |
184 | | int gnutls_x509_crt_set_version(gnutls_x509_crt_t crt, unsigned int version) |
185 | 0 | { |
186 | 0 | int result; |
187 | 0 | unsigned char null = version; |
188 | |
|
189 | 0 | if (crt == NULL || version == 0 || version >= 0x80) { |
190 | 0 | gnutls_assert(); |
191 | 0 | return GNUTLS_E_INVALID_REQUEST; |
192 | 0 | } |
193 | | |
194 | 0 | MODIFIED(crt); |
195 | |
|
196 | 0 | if (null > 0) |
197 | 0 | null--; |
198 | |
|
199 | 0 | result = |
200 | 0 | asn1_write_value(crt->cert, "tbsCertificate.version", &null, 1); |
201 | 0 | if (result != ASN1_SUCCESS) { |
202 | 0 | gnutls_assert(); |
203 | 0 | return _gnutls_asn2err(result); |
204 | 0 | } |
205 | | |
206 | 0 | return 0; |
207 | 0 | } |
208 | | |
209 | | /** |
210 | | * gnutls_x509_crt_set_key: |
211 | | * @crt: a certificate of type #gnutls_x509_crt_t |
212 | | * @key: holds a private key |
213 | | * |
214 | | * This function will set the public parameters from the given |
215 | | * private key to the certificate. |
216 | | * |
217 | | * To export the public key (i.e., the SubjectPublicKeyInfo part), check |
218 | | * gnutls_pubkey_import_x509(). |
219 | | * |
220 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
221 | | * negative error value. |
222 | | * |
223 | | **/ |
224 | | int gnutls_x509_crt_set_key(gnutls_x509_crt_t crt, gnutls_x509_privkey_t key) |
225 | 0 | { |
226 | 0 | int result; |
227 | |
|
228 | 0 | if (crt == NULL) { |
229 | 0 | gnutls_assert(); |
230 | 0 | return GNUTLS_E_INVALID_REQUEST; |
231 | 0 | } |
232 | | |
233 | 0 | MODIFIED(crt); |
234 | |
|
235 | 0 | result = _gnutls_x509_encode_and_copy_PKI_params(crt->cert, |
236 | 0 | "tbsCertificate.subjectPublicKeyInfo", |
237 | 0 | &key->params); |
238 | |
|
239 | 0 | if (result < 0) { |
240 | 0 | gnutls_assert(); |
241 | 0 | return result; |
242 | 0 | } |
243 | | |
244 | 0 | return 0; |
245 | 0 | } |
246 | | |
247 | | /** |
248 | | * gnutls_x509_crt_set_crq: |
249 | | * @crt: a certificate of type #gnutls_x509_crt_t |
250 | | * @crq: holds a certificate request |
251 | | * |
252 | | * This function will set the name and public parameters as well as |
253 | | * the extensions from the given certificate request to the certificate. |
254 | | * Only RSA keys are currently supported. |
255 | | * |
256 | | * Note that this function will only set the @crq if it is self |
257 | | * signed and the signature is correct. See gnutls_x509_crq_sign2(). |
258 | | * |
259 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
260 | | * negative error value. |
261 | | **/ |
262 | | int gnutls_x509_crt_set_crq(gnutls_x509_crt_t crt, gnutls_x509_crq_t crq) |
263 | 0 | { |
264 | 0 | int result; |
265 | |
|
266 | 0 | if (crt == NULL || crq == NULL) { |
267 | 0 | gnutls_assert(); |
268 | 0 | return GNUTLS_E_INVALID_REQUEST; |
269 | 0 | } |
270 | | |
271 | 0 | MODIFIED(crt); |
272 | |
|
273 | 0 | result = gnutls_x509_crq_verify(crq, 0); |
274 | 0 | if (result < 0) |
275 | 0 | return gnutls_assert_val(result); |
276 | | |
277 | 0 | result = asn1_copy_node(crt->cert, "tbsCertificate.subject", |
278 | 0 | crq->crq, "certificationRequestInfo.subject"); |
279 | 0 | if (result != ASN1_SUCCESS) { |
280 | 0 | gnutls_assert(); |
281 | 0 | return _gnutls_asn2err(result); |
282 | 0 | } |
283 | | |
284 | 0 | result = |
285 | 0 | asn1_copy_node(crt->cert, |
286 | 0 | "tbsCertificate.subjectPublicKeyInfo", crq->crq, |
287 | 0 | "certificationRequestInfo.subjectPKInfo"); |
288 | 0 | if (result != ASN1_SUCCESS) { |
289 | 0 | gnutls_assert(); |
290 | 0 | return _gnutls_asn2err(result); |
291 | 0 | } |
292 | | |
293 | 0 | return 0; |
294 | 0 | } |
295 | | |
296 | | /** |
297 | | * gnutls_x509_crt_set_crq_extensions: |
298 | | * @crt: a certificate of type #gnutls_x509_crt_t |
299 | | * @crq: holds a certificate request |
300 | | * |
301 | | * This function will set the extensions from the given request to the |
302 | | * certificate. |
303 | | * |
304 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
305 | | * negative error value. |
306 | | * |
307 | | * Since: 2.8.0 |
308 | | **/ |
309 | | int |
310 | | gnutls_x509_crt_set_crq_extensions(gnutls_x509_crt_t crt, gnutls_x509_crq_t crq) |
311 | 0 | { |
312 | 0 | return gnutls_x509_crt_set_crq_extension_by_oid(crt, crq, NULL, 0); |
313 | 0 | } |
314 | | |
315 | | /** |
316 | | * gnutls_x509_crt_set_crq_extension_by_oid: |
317 | | * @crt: a certificate of type #gnutls_x509_crt_t |
318 | | * @crq: holds a certificate request |
319 | | * @oid: the object identifier of the OID to copy |
320 | | * @flags: should be zero |
321 | | * |
322 | | * This function will set the extension specify by @oid from the given request to the |
323 | | * certificate. |
324 | | * |
325 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
326 | | * negative error value. |
327 | | * |
328 | | * Since: 3.5.1 |
329 | | **/ |
330 | | int |
331 | | gnutls_x509_crt_set_crq_extension_by_oid(gnutls_x509_crt_t crt, |
332 | | gnutls_x509_crq_t crq, const char *oid, |
333 | | unsigned flags) |
334 | 0 | { |
335 | 0 | size_t i; |
336 | |
|
337 | 0 | if (crt == NULL || crq == NULL) { |
338 | 0 | gnutls_assert(); |
339 | 0 | return GNUTLS_E_INVALID_REQUEST; |
340 | 0 | } |
341 | | |
342 | 0 | MODIFIED(crt); |
343 | |
|
344 | 0 | for (i = 0;; i++) { |
345 | 0 | int result; |
346 | 0 | char local_oid[MAX_OID_SIZE]; |
347 | 0 | size_t local_oid_size; |
348 | 0 | uint8_t *extensions; |
349 | 0 | size_t extensions_size; |
350 | 0 | unsigned int critical; |
351 | 0 | gnutls_datum_t ext; |
352 | |
|
353 | 0 | local_oid_size = sizeof(local_oid); |
354 | 0 | result = gnutls_x509_crq_get_extension_info(crq, i, local_oid, |
355 | 0 | &local_oid_size, |
356 | 0 | &critical); |
357 | 0 | if (result < 0) { |
358 | 0 | if (result == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) |
359 | 0 | break; |
360 | | |
361 | 0 | gnutls_assert(); |
362 | 0 | return result; |
363 | 0 | } |
364 | | |
365 | 0 | if (oid && strcmp(local_oid, oid) != 0) |
366 | 0 | continue; |
367 | | |
368 | 0 | extensions_size = 0; |
369 | 0 | result = gnutls_x509_crq_get_extension_data(crq, i, NULL, |
370 | 0 | &extensions_size); |
371 | 0 | if (result < 0) { |
372 | 0 | gnutls_assert(); |
373 | 0 | return result; |
374 | 0 | } |
375 | | |
376 | 0 | extensions = gnutls_malloc(extensions_size); |
377 | 0 | if (extensions == NULL) { |
378 | 0 | gnutls_assert(); |
379 | 0 | return GNUTLS_E_MEMORY_ERROR; |
380 | 0 | } |
381 | | |
382 | 0 | result = |
383 | 0 | gnutls_x509_crq_get_extension_data(crq, i, extensions, |
384 | 0 | &extensions_size); |
385 | 0 | if (result < 0) { |
386 | 0 | gnutls_assert(); |
387 | 0 | gnutls_free(extensions); |
388 | 0 | return result; |
389 | 0 | } |
390 | | |
391 | 0 | ext.data = extensions; |
392 | 0 | ext.size = extensions_size; |
393 | |
|
394 | 0 | result = |
395 | 0 | _gnutls_x509_crt_set_extension(crt, local_oid, &ext, |
396 | 0 | critical); |
397 | 0 | gnutls_free(extensions); |
398 | 0 | if (result < 0) { |
399 | 0 | gnutls_assert(); |
400 | 0 | return result; |
401 | 0 | } |
402 | 0 | } |
403 | | |
404 | 0 | return 0; |
405 | 0 | } |
406 | | |
407 | | /** |
408 | | * gnutls_x509_crt_set_extension_by_oid: |
409 | | * @crt: a certificate of type #gnutls_x509_crt_t |
410 | | * @oid: holds an Object Identifier in null terminated string |
411 | | * @buf: a pointer to a DER encoded data |
412 | | * @sizeof_buf: holds the size of @buf |
413 | | * @critical: should be non-zero if the extension is to be marked as critical |
414 | | * |
415 | | * This function will set an the extension, by the specified OID, in |
416 | | * the certificate. The extension data should be binary data DER |
417 | | * encoded. |
418 | | * |
419 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
420 | | * negative error value. |
421 | | **/ |
422 | | int |
423 | | gnutls_x509_crt_set_extension_by_oid(gnutls_x509_crt_t crt, |
424 | | const char *oid, const void *buf, |
425 | | size_t sizeof_buf, unsigned int critical) |
426 | 0 | { |
427 | 0 | int result; |
428 | 0 | gnutls_datum_t der_data; |
429 | |
|
430 | 0 | der_data.data = (void *)buf; |
431 | 0 | der_data.size = sizeof_buf; |
432 | |
|
433 | 0 | if (crt == NULL) { |
434 | 0 | gnutls_assert(); |
435 | 0 | return GNUTLS_E_INVALID_REQUEST; |
436 | 0 | } |
437 | | |
438 | 0 | result = _gnutls_x509_crt_set_extension(crt, oid, &der_data, critical); |
439 | 0 | if (result < 0) { |
440 | 0 | gnutls_assert(); |
441 | 0 | return result; |
442 | 0 | } |
443 | | |
444 | 0 | return 0; |
445 | |
|
446 | 0 | } |
447 | | |
448 | | /** |
449 | | * gnutls_x509_crt_set_basic_constraints: |
450 | | * @crt: a certificate of type #gnutls_x509_crt_t |
451 | | * @ca: true(1) or false(0). Depending on the Certificate authority status. |
452 | | * @pathLenConstraint: non-negative error codes indicate maximum length of path, |
453 | | * and negative error codes indicate that the pathLenConstraints field should |
454 | | * not be present. |
455 | | * |
456 | | * This function will set the basicConstraints certificate extension. |
457 | | * |
458 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
459 | | * negative error value. |
460 | | **/ |
461 | | int |
462 | | gnutls_x509_crt_set_basic_constraints(gnutls_x509_crt_t crt, |
463 | | unsigned int ca, int pathLenConstraint) |
464 | 0 | { |
465 | 0 | int result; |
466 | 0 | gnutls_datum_t der_data; |
467 | |
|
468 | 0 | if (crt == NULL) { |
469 | 0 | gnutls_assert(); |
470 | 0 | return GNUTLS_E_INVALID_REQUEST; |
471 | 0 | } |
472 | | |
473 | | /* generate the extension. |
474 | | */ |
475 | 0 | result = |
476 | 0 | gnutls_x509_ext_export_basic_constraints(ca, pathLenConstraint, |
477 | 0 | &der_data); |
478 | 0 | if (result < 0) { |
479 | 0 | gnutls_assert(); |
480 | 0 | return result; |
481 | 0 | } |
482 | | |
483 | 0 | result = _gnutls_x509_crt_set_extension(crt, "2.5.29.19", &der_data, 1); |
484 | |
|
485 | 0 | _gnutls_free_datum(&der_data); |
486 | |
|
487 | 0 | if (result < 0) { |
488 | 0 | gnutls_assert(); |
489 | 0 | return result; |
490 | 0 | } |
491 | | |
492 | 0 | return 0; |
493 | 0 | } |
494 | | |
495 | | /** |
496 | | * gnutls_x509_crt_set_ca_status: |
497 | | * @crt: a certificate of type #gnutls_x509_crt_t |
498 | | * @ca: true(1) or false(0). Depending on the Certificate authority status. |
499 | | * |
500 | | * This function will set the basicConstraints certificate extension. |
501 | | * Use gnutls_x509_crt_set_basic_constraints() if you want to control |
502 | | * the pathLenConstraint field too. |
503 | | * |
504 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
505 | | * negative error value. |
506 | | **/ |
507 | | int gnutls_x509_crt_set_ca_status(gnutls_x509_crt_t crt, unsigned int ca) |
508 | 0 | { |
509 | 0 | return gnutls_x509_crt_set_basic_constraints(crt, ca, -1); |
510 | 0 | } |
511 | | |
512 | | /** |
513 | | * gnutls_x509_crt_set_key_usage: |
514 | | * @crt: a certificate of type #gnutls_x509_crt_t |
515 | | * @usage: an ORed sequence of the GNUTLS_KEY_* elements. |
516 | | * |
517 | | * This function will set the keyUsage certificate extension. |
518 | | * |
519 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
520 | | * negative error value. |
521 | | **/ |
522 | | int gnutls_x509_crt_set_key_usage(gnutls_x509_crt_t crt, unsigned int usage) |
523 | 0 | { |
524 | 0 | int result; |
525 | 0 | gnutls_datum_t der_data; |
526 | |
|
527 | 0 | if (crt == NULL) { |
528 | 0 | gnutls_assert(); |
529 | 0 | return GNUTLS_E_INVALID_REQUEST; |
530 | 0 | } |
531 | | |
532 | | /* generate the extension. |
533 | | */ |
534 | 0 | result = gnutls_x509_ext_export_key_usage(usage, &der_data); |
535 | 0 | if (result < 0) { |
536 | 0 | gnutls_assert(); |
537 | 0 | return result; |
538 | 0 | } |
539 | | |
540 | 0 | result = _gnutls_x509_crt_set_extension(crt, "2.5.29.15", &der_data, 1); |
541 | |
|
542 | 0 | _gnutls_free_datum(&der_data); |
543 | |
|
544 | 0 | if (result < 0) { |
545 | 0 | gnutls_assert(); |
546 | 0 | return result; |
547 | 0 | } |
548 | | |
549 | 0 | return 0; |
550 | 0 | } |
551 | | |
552 | | /** |
553 | | * gnutls_x509_crt_set_inhibit_anypolicy: |
554 | | * @crt: a certificate of type #gnutls_x509_crt_t |
555 | | * @skipcerts: number of certificates after which anypolicy is no longer acceptable. |
556 | | * |
557 | | * This function will set the Inhibit anyPolicy certificate extension. |
558 | | * |
559 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
560 | | * negative error value. |
561 | | **/ |
562 | | int |
563 | | gnutls_x509_crt_set_inhibit_anypolicy(gnutls_x509_crt_t crt, |
564 | | unsigned int skipcerts) |
565 | 0 | { |
566 | 0 | int ret; |
567 | 0 | gnutls_datum_t der_data; |
568 | |
|
569 | 0 | if (crt == NULL) { |
570 | 0 | gnutls_assert(); |
571 | 0 | return GNUTLS_E_INVALID_REQUEST; |
572 | 0 | } |
573 | | |
574 | | /* generate the extension. |
575 | | */ |
576 | 0 | ret = gnutls_x509_ext_export_inhibit_anypolicy(skipcerts, &der_data); |
577 | 0 | if (ret < 0) { |
578 | 0 | gnutls_assert(); |
579 | 0 | return ret; |
580 | 0 | } |
581 | | |
582 | 0 | ret = _gnutls_x509_crt_set_extension(crt, "2.5.29.54", &der_data, 1); |
583 | 0 | _gnutls_free_datum(&der_data); |
584 | |
|
585 | 0 | if (ret < 0) { |
586 | 0 | gnutls_assert(); |
587 | 0 | return ret; |
588 | 0 | } |
589 | | |
590 | 0 | return 0; |
591 | 0 | } |
592 | | |
593 | | /** |
594 | | * gnutls_x509_crt_set_subject_alternative_name: |
595 | | * @crt: a certificate of type #gnutls_x509_crt_t |
596 | | * @type: is one of the gnutls_x509_subject_alt_name_t enumerations |
597 | | * @data_string: The data to be set, a (0) terminated string |
598 | | * |
599 | | * This function will set the subject alternative name certificate |
600 | | * extension. This function assumes that data can be expressed as a null |
601 | | * terminated string. |
602 | | * |
603 | | * The name of the function is unfortunate since it is inconsistent with |
604 | | * gnutls_x509_crt_get_subject_alt_name(). |
605 | | * |
606 | | * See gnutls_x509_crt_set_subject_alt_name() for more information. |
607 | | * |
608 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
609 | | * negative error value. |
610 | | **/ |
611 | | int |
612 | | gnutls_x509_crt_set_subject_alternative_name(gnutls_x509_crt_t crt, |
613 | | gnutls_x509_subject_alt_name_t |
614 | | type, const char *data_string) |
615 | 0 | { |
616 | 0 | if (crt == NULL) { |
617 | 0 | gnutls_assert(); |
618 | 0 | return GNUTLS_E_INVALID_REQUEST; |
619 | 0 | } |
620 | | |
621 | | /* only handle text extensions */ |
622 | 0 | if (type != GNUTLS_SAN_DNSNAME && type != GNUTLS_SAN_RFC822NAME && |
623 | 0 | type != GNUTLS_SAN_URI) { |
624 | 0 | gnutls_assert(); |
625 | 0 | return GNUTLS_E_INVALID_REQUEST; |
626 | 0 | } |
627 | | |
628 | 0 | return gnutls_x509_crt_set_subject_alt_name(crt, type, data_string, |
629 | 0 | strlen(data_string), |
630 | 0 | GNUTLS_FSAN_SET); |
631 | 0 | } |
632 | | |
633 | | /** |
634 | | * gnutls_x509_crt_set_subject_alt_name: |
635 | | * @crt: a certificate of type #gnutls_x509_crt_t |
636 | | * @type: is one of the gnutls_x509_subject_alt_name_t enumerations |
637 | | * @data: The data to be set |
638 | | * @data_size: The size of data to be set |
639 | | * @flags: GNUTLS_FSAN_SET to clear previous data or GNUTLS_FSAN_APPEND to append. |
640 | | * |
641 | | * This function will set the subject alternative name certificate |
642 | | * extension. It can set the following types: %GNUTLS_SAN_DNSNAME as a text string, |
643 | | * %GNUTLS_SAN_RFC822NAME as a text string, %GNUTLS_SAN_URI as a text string, |
644 | | * %GNUTLS_SAN_IPADDRESS as a binary IP address (4 or 16 bytes), |
645 | | * %GNUTLS_SAN_OTHERNAME_XMPP as a UTF8 string (since 3.5.0). |
646 | | * |
647 | | * Since version 3.5.7 the %GNUTLS_SAN_RFC822NAME, %GNUTLS_SAN_DNSNAME, and |
648 | | * %GNUTLS_SAN_OTHERNAME_XMPP are converted to ACE format when necessary. |
649 | | * |
650 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
651 | | * negative error value. |
652 | | * |
653 | | * Since: 2.6.0 |
654 | | **/ |
655 | | int |
656 | | gnutls_x509_crt_set_subject_alt_name(gnutls_x509_crt_t crt, |
657 | | gnutls_x509_subject_alt_name_t type, |
658 | | const void *data, |
659 | | unsigned int data_size, unsigned int flags) |
660 | 0 | { |
661 | 0 | int result; |
662 | 0 | gnutls_datum_t der_data = { NULL, 0 }; |
663 | 0 | gnutls_datum_t prev_der_data = { NULL, 0 }; |
664 | 0 | unsigned int critical = 0; |
665 | |
|
666 | 0 | if (crt == NULL) { |
667 | 0 | gnutls_assert(); |
668 | 0 | return GNUTLS_E_INVALID_REQUEST; |
669 | 0 | } |
670 | | |
671 | | /* Check if the extension already exists. |
672 | | */ |
673 | | |
674 | 0 | if (flags & GNUTLS_FSAN_APPEND) { |
675 | 0 | result = |
676 | 0 | _gnutls_x509_crt_get_extension(crt, "2.5.29.17", 0, |
677 | 0 | &prev_der_data, &critical); |
678 | 0 | if (result < 0 |
679 | 0 | && result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { |
680 | 0 | gnutls_assert(); |
681 | 0 | return result; |
682 | 0 | } |
683 | 0 | } |
684 | | |
685 | | /* generate the extension. |
686 | | */ |
687 | 0 | result = |
688 | 0 | _gnutls_x509_ext_gen_subject_alt_name(type, NULL, data, data_size, |
689 | 0 | &prev_der_data, &der_data); |
690 | |
|
691 | 0 | if (result < 0) { |
692 | 0 | gnutls_assert(); |
693 | 0 | goto finish; |
694 | 0 | } |
695 | | |
696 | 0 | result = |
697 | 0 | _gnutls_x509_crt_set_extension(crt, "2.5.29.17", &der_data, |
698 | 0 | critical); |
699 | |
|
700 | 0 | _gnutls_free_datum(&der_data); |
701 | |
|
702 | 0 | if (result < 0) { |
703 | 0 | gnutls_assert(); |
704 | 0 | return result; |
705 | 0 | } |
706 | | |
707 | 0 | result = 0; |
708 | |
|
709 | 0 | finish: |
710 | 0 | _gnutls_free_datum(&prev_der_data); |
711 | 0 | return result; |
712 | 0 | } |
713 | | |
714 | | /** |
715 | | * gnutls_x509_crt_set_issuer_alt_name: |
716 | | * @crt: a certificate of type #gnutls_x509_crt_t |
717 | | * @type: is one of the gnutls_x509_subject_alt_name_t enumerations |
718 | | * @data: The data to be set |
719 | | * @data_size: The size of data to be set |
720 | | * @flags: GNUTLS_FSAN_SET to clear previous data or GNUTLS_FSAN_APPEND to append. |
721 | | * |
722 | | * This function will set the issuer alternative name certificate |
723 | | * extension. It can set the same types as gnutls_x509_crt_set_subject_alt_name(). |
724 | | * |
725 | | * Since version 3.5.7 the %GNUTLS_SAN_RFC822NAME, %GNUTLS_SAN_DNSNAME, and |
726 | | * %GNUTLS_SAN_OTHERNAME_XMPP are converted to ACE format when necessary. |
727 | | * |
728 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
729 | | * negative error value. |
730 | | * |
731 | | * Since: 3.3.0 |
732 | | **/ |
733 | | int |
734 | | gnutls_x509_crt_set_issuer_alt_name(gnutls_x509_crt_t crt, |
735 | | gnutls_x509_subject_alt_name_t type, |
736 | | const void *data, |
737 | | unsigned int data_size, unsigned int flags) |
738 | 0 | { |
739 | 0 | int result; |
740 | 0 | gnutls_datum_t der_data = { NULL, 0 }; |
741 | 0 | gnutls_datum_t prev_der_data = { NULL, 0 }; |
742 | 0 | unsigned int critical = 0; |
743 | |
|
744 | 0 | if (crt == NULL) { |
745 | 0 | gnutls_assert(); |
746 | 0 | return GNUTLS_E_INVALID_REQUEST; |
747 | 0 | } |
748 | | |
749 | | /* Check if the extension already exists. |
750 | | */ |
751 | | |
752 | 0 | if (flags & GNUTLS_FSAN_APPEND) { |
753 | 0 | result = |
754 | 0 | _gnutls_x509_crt_get_extension(crt, "2.5.29.18", 0, |
755 | 0 | &prev_der_data, &critical); |
756 | 0 | if (result < 0 |
757 | 0 | && result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { |
758 | 0 | gnutls_assert(); |
759 | 0 | return result; |
760 | 0 | } |
761 | 0 | } |
762 | | |
763 | | /* generate the extension. |
764 | | */ |
765 | 0 | result = |
766 | 0 | _gnutls_x509_ext_gen_subject_alt_name(type, NULL, data, data_size, |
767 | 0 | &prev_der_data, &der_data); |
768 | |
|
769 | 0 | if (result < 0) { |
770 | 0 | gnutls_assert(); |
771 | 0 | goto finish; |
772 | 0 | } |
773 | | |
774 | 0 | result = |
775 | 0 | _gnutls_x509_crt_set_extension(crt, "2.5.29.18", &der_data, |
776 | 0 | critical); |
777 | |
|
778 | 0 | _gnutls_free_datum(&der_data); |
779 | |
|
780 | 0 | if (result < 0) { |
781 | 0 | gnutls_assert(); |
782 | 0 | return result; |
783 | 0 | } |
784 | | |
785 | 0 | result = 0; |
786 | |
|
787 | 0 | finish: |
788 | 0 | _gnutls_free_datum(&prev_der_data); |
789 | 0 | return result; |
790 | 0 | } |
791 | | |
792 | | int _gnutls_encode_othername_data(unsigned flags, const void *data, |
793 | | unsigned data_size, gnutls_datum_t * output) |
794 | 0 | { |
795 | 0 | int ret; |
796 | 0 | if (flags & GNUTLS_FSAN_ENCODE_OCTET_STRING) { |
797 | 0 | ret = _gnutls_x509_encode_string(ASN1_ETYPE_OCTET_STRING, |
798 | 0 | data, data_size, output); |
799 | 0 | } else if (flags & GNUTLS_FSAN_ENCODE_UTF8_STRING) { |
800 | 0 | ret = _gnutls_x509_encode_string(ASN1_ETYPE_UTF8_STRING, |
801 | 0 | data, data_size, output); |
802 | 0 | } else { |
803 | 0 | ret = _gnutls_set_datum(output, data, data_size); |
804 | 0 | } |
805 | 0 | return ret; |
806 | 0 | } |
807 | | |
808 | | /** |
809 | | * gnutls_x509_crt_set_subject_alt_othername: |
810 | | * @crt: a certificate of type #gnutls_x509_crt_t |
811 | | * @oid: The other name OID |
812 | | * @data: The data to be set |
813 | | * @data_size: The size of data to be set |
814 | | * @flags: GNUTLS_FSAN_SET to clear previous data or GNUTLS_FSAN_APPEND to append. |
815 | | * |
816 | | * This function will set an "othername" to the subject alternative name certificate |
817 | | * extension. |
818 | | * |
819 | | * The values set are set as binary values and are expected to have the proper DER encoding. |
820 | | * For convenience the flags %GNUTLS_FSAN_ENCODE_OCTET_STRING and %GNUTLS_FSAN_ENCODE_UTF8_STRING |
821 | | * can be used to encode the provided data. |
822 | | * |
823 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
824 | | * negative error value. |
825 | | * |
826 | | * Since: 3.5.0 |
827 | | **/ |
828 | | int |
829 | | gnutls_x509_crt_set_subject_alt_othername(gnutls_x509_crt_t crt, |
830 | | const char *oid, |
831 | | const void *data, |
832 | | unsigned int data_size, |
833 | | unsigned int flags) |
834 | 0 | { |
835 | 0 | int result; |
836 | 0 | gnutls_datum_t der_data = { NULL, 0 }; |
837 | 0 | gnutls_datum_t prev_der_data = { NULL, 0 }; |
838 | 0 | gnutls_datum_t encoded_data = { NULL, 0 }; |
839 | 0 | unsigned int critical = 0; |
840 | |
|
841 | 0 | if (crt == NULL) { |
842 | 0 | gnutls_assert(); |
843 | 0 | return GNUTLS_E_INVALID_REQUEST; |
844 | 0 | } |
845 | | |
846 | | /* Check if the extension already exists. |
847 | | */ |
848 | | |
849 | 0 | if (flags & GNUTLS_FSAN_APPEND) { |
850 | 0 | result = |
851 | 0 | _gnutls_x509_crt_get_extension(crt, "2.5.29.17", 0, |
852 | 0 | &prev_der_data, &critical); |
853 | 0 | if (result < 0 |
854 | 0 | && result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { |
855 | 0 | gnutls_assert(); |
856 | 0 | return result; |
857 | 0 | } |
858 | 0 | } |
859 | | |
860 | 0 | result = |
861 | 0 | _gnutls_encode_othername_data(flags, data, data_size, |
862 | 0 | &encoded_data); |
863 | 0 | if (result < 0) { |
864 | 0 | gnutls_assert(); |
865 | 0 | goto finish; |
866 | 0 | } |
867 | | |
868 | | /* generate the extension. |
869 | | */ |
870 | 0 | result = |
871 | 0 | _gnutls_x509_ext_gen_subject_alt_name(GNUTLS_SAN_OTHERNAME, oid, |
872 | 0 | encoded_data.data, |
873 | 0 | encoded_data.size, |
874 | 0 | &prev_der_data, &der_data); |
875 | |
|
876 | 0 | if (result < 0) { |
877 | 0 | gnutls_assert(); |
878 | 0 | goto finish; |
879 | 0 | } |
880 | | |
881 | 0 | result = |
882 | 0 | _gnutls_x509_crt_set_extension(crt, "2.5.29.17", &der_data, |
883 | 0 | critical); |
884 | |
|
885 | 0 | if (result < 0) { |
886 | 0 | gnutls_assert(); |
887 | 0 | goto finish; |
888 | 0 | } |
889 | | |
890 | 0 | result = 0; |
891 | |
|
892 | 0 | finish: |
893 | 0 | _gnutls_free_datum(&der_data); |
894 | 0 | _gnutls_free_datum(&prev_der_data); |
895 | 0 | _gnutls_free_datum(&encoded_data); |
896 | 0 | return result; |
897 | 0 | } |
898 | | |
899 | | /** |
900 | | * gnutls_x509_crt_set_issuer_alt_othername: |
901 | | * @crt: a certificate of type #gnutls_x509_crt_t |
902 | | * @oid: The other name OID |
903 | | * @data: The data to be set |
904 | | * @data_size: The size of data to be set |
905 | | * @flags: GNUTLS_FSAN_SET to clear previous data or GNUTLS_FSAN_APPEND to append. |
906 | | * |
907 | | * This function will set an "othername" to the issuer alternative name certificate |
908 | | * extension. |
909 | | * |
910 | | * The values set are set as binary values and are expected to have the proper DER encoding. |
911 | | * For convenience the flags %GNUTLS_FSAN_ENCODE_OCTET_STRING and %GNUTLS_FSAN_ENCODE_UTF8_STRING |
912 | | * can be used to encode the provided data. |
913 | | * |
914 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
915 | | * negative error value. |
916 | | * |
917 | | * Since: 3.5.0 |
918 | | **/ |
919 | | int |
920 | | gnutls_x509_crt_set_issuer_alt_othername(gnutls_x509_crt_t crt, |
921 | | const char *oid, |
922 | | const void *data, |
923 | | unsigned int data_size, |
924 | | unsigned int flags) |
925 | 0 | { |
926 | 0 | int result; |
927 | 0 | gnutls_datum_t der_data = { NULL, 0 }; |
928 | 0 | gnutls_datum_t prev_der_data = { NULL, 0 }; |
929 | 0 | gnutls_datum_t encoded_data = { NULL, 0 }; |
930 | 0 | unsigned int critical = 0; |
931 | |
|
932 | 0 | if (crt == NULL) { |
933 | 0 | gnutls_assert(); |
934 | 0 | return GNUTLS_E_INVALID_REQUEST; |
935 | 0 | } |
936 | | |
937 | | /* Check if the extension already exists. |
938 | | */ |
939 | | |
940 | 0 | if (flags & GNUTLS_FSAN_APPEND) { |
941 | 0 | result = |
942 | 0 | _gnutls_x509_crt_get_extension(crt, "2.5.29.18", 0, |
943 | 0 | &prev_der_data, &critical); |
944 | 0 | if (result < 0 |
945 | 0 | && result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { |
946 | 0 | gnutls_assert(); |
947 | 0 | return result; |
948 | 0 | } |
949 | 0 | } |
950 | | |
951 | 0 | result = |
952 | 0 | _gnutls_encode_othername_data(flags, data, data_size, |
953 | 0 | &encoded_data); |
954 | 0 | if (result < 0) { |
955 | 0 | gnutls_assert(); |
956 | 0 | goto finish; |
957 | 0 | } |
958 | | |
959 | | /* generate the extension. |
960 | | */ |
961 | 0 | result = |
962 | 0 | _gnutls_x509_ext_gen_subject_alt_name(GNUTLS_SAN_OTHERNAME, oid, |
963 | 0 | encoded_data.data, |
964 | 0 | encoded_data.size, |
965 | 0 | &prev_der_data, &der_data); |
966 | 0 | if (result < 0) { |
967 | 0 | gnutls_assert(); |
968 | 0 | goto finish; |
969 | 0 | } |
970 | | |
971 | 0 | result = |
972 | 0 | _gnutls_x509_crt_set_extension(crt, "2.5.29.18", &der_data, |
973 | 0 | critical); |
974 | |
|
975 | 0 | if (result < 0) { |
976 | 0 | gnutls_assert(); |
977 | 0 | goto finish; |
978 | 0 | } |
979 | | |
980 | 0 | result = 0; |
981 | |
|
982 | 0 | finish: |
983 | 0 | _gnutls_free_datum(&der_data); |
984 | 0 | _gnutls_free_datum(&prev_der_data); |
985 | 0 | _gnutls_free_datum(&encoded_data); |
986 | 0 | return result; |
987 | 0 | } |
988 | | |
989 | | /** |
990 | | * gnutls_x509_crt_set_proxy: |
991 | | * @crt: a certificate of type #gnutls_x509_crt_t |
992 | | * @pathLenConstraint: non-negative error codes indicate maximum length of path, |
993 | | * and negative error codes indicate that the pathLenConstraints field should |
994 | | * not be present. |
995 | | * @policyLanguage: OID describing the language of @policy. |
996 | | * @policy: uint8_t byte array with policy language, can be %NULL |
997 | | * @sizeof_policy: size of @policy. |
998 | | * |
999 | | * This function will set the proxyCertInfo extension. |
1000 | | * |
1001 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1002 | | * negative error value. |
1003 | | **/ |
1004 | | int |
1005 | | gnutls_x509_crt_set_proxy(gnutls_x509_crt_t crt, |
1006 | | int pathLenConstraint, |
1007 | | const char *policyLanguage, |
1008 | | const char *policy, size_t sizeof_policy) |
1009 | 0 | { |
1010 | 0 | int result; |
1011 | 0 | gnutls_datum_t der_data; |
1012 | |
|
1013 | 0 | if (crt == NULL) { |
1014 | 0 | gnutls_assert(); |
1015 | 0 | return GNUTLS_E_INVALID_REQUEST; |
1016 | 0 | } |
1017 | | |
1018 | | /* generate the extension. |
1019 | | */ |
1020 | 0 | result = gnutls_x509_ext_export_proxy(pathLenConstraint, |
1021 | 0 | policyLanguage, |
1022 | 0 | policy, sizeof_policy, &der_data); |
1023 | 0 | if (result < 0) { |
1024 | 0 | gnutls_assert(); |
1025 | 0 | return result; |
1026 | 0 | } |
1027 | | |
1028 | 0 | result = _gnutls_x509_crt_set_extension(crt, "1.3.6.1.5.5.7.1.14", |
1029 | 0 | &der_data, 1); |
1030 | |
|
1031 | 0 | _gnutls_free_datum(&der_data); |
1032 | |
|
1033 | 0 | if (result < 0) { |
1034 | 0 | gnutls_assert(); |
1035 | 0 | return result; |
1036 | 0 | } |
1037 | | |
1038 | 0 | return 0; |
1039 | 0 | } |
1040 | | |
1041 | | /** |
1042 | | * gnutls_x509_crt_set_private_key_usage_period: |
1043 | | * @crt: a certificate of type #gnutls_x509_crt_t |
1044 | | * @activation: The activation time |
1045 | | * @expiration: The expiration time |
1046 | | * |
1047 | | * This function will set the private key usage period extension (2.5.29.16). |
1048 | | * |
1049 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1050 | | * negative error value. |
1051 | | **/ |
1052 | | int |
1053 | | gnutls_x509_crt_set_private_key_usage_period(gnutls_x509_crt_t crt, |
1054 | | time_t activation, |
1055 | | time_t expiration) |
1056 | 0 | { |
1057 | 0 | int result; |
1058 | 0 | gnutls_datum_t der_data; |
1059 | |
|
1060 | 0 | if (crt == NULL) { |
1061 | 0 | gnutls_assert(); |
1062 | 0 | return GNUTLS_E_INVALID_REQUEST; |
1063 | 0 | } |
1064 | | |
1065 | 0 | result = gnutls_x509_ext_export_private_key_usage_period(activation, |
1066 | 0 | expiration, |
1067 | 0 | &der_data); |
1068 | 0 | if (result < 0) { |
1069 | 0 | gnutls_assert(); |
1070 | 0 | goto cleanup; |
1071 | 0 | } |
1072 | | |
1073 | 0 | result = _gnutls_x509_crt_set_extension(crt, "2.5.29.16", &der_data, 0); |
1074 | |
|
1075 | 0 | _gnutls_free_datum(&der_data); |
1076 | |
|
1077 | 0 | cleanup: |
1078 | 0 | return result; |
1079 | 0 | } |
1080 | | |
1081 | | /** |
1082 | | * gnutls_x509_crt_sign2: |
1083 | | * @crt: a certificate of type #gnutls_x509_crt_t |
1084 | | * @issuer: is the certificate of the certificate issuer |
1085 | | * @issuer_key: holds the issuer's private key |
1086 | | * @dig: The message digest to use, %GNUTLS_DIG_SHA256 is a safe choice |
1087 | | * @flags: must be 0 |
1088 | | * |
1089 | | * This function will sign the certificate with the issuer's private key, and |
1090 | | * will copy the issuer's information into the certificate. |
1091 | | * |
1092 | | * This must be the last step in a certificate generation since all |
1093 | | * the previously set parameters are now signed. |
1094 | | * |
1095 | | * A known limitation of this function is, that a newly-signed certificate will not |
1096 | | * be fully functional (e.g., for signature verification), until it |
1097 | | * is exported an re-imported. |
1098 | | * |
1099 | | * After GnuTLS 3.6.1 the value of @dig may be %GNUTLS_DIG_UNKNOWN, |
1100 | | * and in that case, a suitable but reasonable for the key algorithm will be selected. |
1101 | | * |
1102 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1103 | | * negative error value. |
1104 | | **/ |
1105 | | int |
1106 | | gnutls_x509_crt_sign2(gnutls_x509_crt_t crt, gnutls_x509_crt_t issuer, |
1107 | | gnutls_x509_privkey_t issuer_key, |
1108 | | gnutls_digest_algorithm_t dig, unsigned int flags) |
1109 | 0 | { |
1110 | 0 | int result; |
1111 | 0 | gnutls_privkey_t privkey; |
1112 | |
|
1113 | 0 | if (crt == NULL || issuer == NULL || issuer_key == NULL) { |
1114 | 0 | gnutls_assert(); |
1115 | 0 | return GNUTLS_E_INVALID_REQUEST; |
1116 | 0 | } |
1117 | | |
1118 | 0 | MODIFIED(crt); |
1119 | |
|
1120 | 0 | result = gnutls_privkey_init(&privkey); |
1121 | 0 | if (result < 0) { |
1122 | 0 | gnutls_assert(); |
1123 | 0 | return result; |
1124 | 0 | } |
1125 | | |
1126 | 0 | result = gnutls_privkey_import_x509(privkey, issuer_key, 0); |
1127 | 0 | if (result < 0) { |
1128 | 0 | gnutls_assert(); |
1129 | 0 | goto fail; |
1130 | 0 | } |
1131 | | |
1132 | 0 | result = gnutls_x509_crt_privkey_sign(crt, issuer, privkey, dig, flags); |
1133 | 0 | if (result < 0) { |
1134 | 0 | gnutls_assert(); |
1135 | 0 | goto fail; |
1136 | 0 | } |
1137 | | |
1138 | 0 | result = 0; |
1139 | |
|
1140 | 0 | fail: |
1141 | 0 | gnutls_privkey_deinit(privkey); |
1142 | |
|
1143 | 0 | return result; |
1144 | 0 | } |
1145 | | |
1146 | | /** |
1147 | | * gnutls_x509_crt_sign: |
1148 | | * @crt: a certificate of type #gnutls_x509_crt_t |
1149 | | * @issuer: is the certificate of the certificate issuer |
1150 | | * @issuer_key: holds the issuer's private key |
1151 | | * |
1152 | | * This function is the same a gnutls_x509_crt_sign2() with no flags, |
1153 | | * and an appropriate hash algorithm. The hash algorithm used may |
1154 | | * vary between versions of GnuTLS, and it is tied to the security |
1155 | | * level of the issuer's public key. |
1156 | | * |
1157 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1158 | | * negative error value. |
1159 | | **/ |
1160 | | int |
1161 | | gnutls_x509_crt_sign(gnutls_x509_crt_t crt, gnutls_x509_crt_t issuer, |
1162 | | gnutls_x509_privkey_t issuer_key) |
1163 | 0 | { |
1164 | 0 | return gnutls_x509_crt_sign2(crt, issuer, issuer_key, 0, 0); |
1165 | 0 | } |
1166 | | |
1167 | | /** |
1168 | | * gnutls_x509_crt_set_activation_time: |
1169 | | * @cert: a certificate of type #gnutls_x509_crt_t |
1170 | | * @act_time: The actual time |
1171 | | * |
1172 | | * This function will set the time this certificate was or will be |
1173 | | * activated. |
1174 | | * |
1175 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1176 | | * negative error value. |
1177 | | **/ |
1178 | | int gnutls_x509_crt_set_activation_time(gnutls_x509_crt_t cert, time_t act_time) |
1179 | 0 | { |
1180 | 0 | if (cert == NULL) { |
1181 | 0 | gnutls_assert(); |
1182 | 0 | return GNUTLS_E_INVALID_REQUEST; |
1183 | 0 | } |
1184 | | |
1185 | 0 | MODIFIED(cert); |
1186 | |
|
1187 | 0 | return _gnutls_x509_set_time(cert->cert, |
1188 | 0 | "tbsCertificate.validity.notBefore", |
1189 | 0 | act_time, 0); |
1190 | 0 | } |
1191 | | |
1192 | | /** |
1193 | | * gnutls_x509_crt_set_expiration_time: |
1194 | | * @cert: a certificate of type #gnutls_x509_crt_t |
1195 | | * @exp_time: The actual time |
1196 | | * |
1197 | | * This function will set the time this Certificate will expire. |
1198 | | * Setting an expiration time to (time_t)-1 will set |
1199 | | * to the no well-defined expiration date value. |
1200 | | * |
1201 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1202 | | * negative error value. |
1203 | | **/ |
1204 | | int gnutls_x509_crt_set_expiration_time(gnutls_x509_crt_t cert, time_t exp_time) |
1205 | 0 | { |
1206 | 0 | if (cert == NULL) { |
1207 | 0 | gnutls_assert(); |
1208 | 0 | return GNUTLS_E_INVALID_REQUEST; |
1209 | 0 | } |
1210 | | |
1211 | 0 | MODIFIED(cert); |
1212 | |
|
1213 | 0 | return _gnutls_x509_set_time(cert->cert, |
1214 | 0 | "tbsCertificate.validity.notAfter", |
1215 | 0 | exp_time, 0); |
1216 | 0 | } |
1217 | | |
1218 | | /** |
1219 | | * gnutls_x509_crt_set_serial: |
1220 | | * @cert: a certificate of type #gnutls_x509_crt_t |
1221 | | * @serial: The serial number |
1222 | | * @serial_size: Holds the size of the serial field. |
1223 | | * |
1224 | | * This function will set the X.509 certificate's serial number. |
1225 | | * While the serial number is an integer, it is often handled |
1226 | | * as an opaque field by several CAs. For this reason this function |
1227 | | * accepts any kind of data as a serial number. To be consistent |
1228 | | * with the X.509/PKIX specifications the provided @serial should be |
1229 | | * a big-endian positive number (i.e. its leftmost bit should be zero). |
1230 | | * |
1231 | | * The size of the serial is restricted to 20 bytes maximum by RFC5280. |
1232 | | * This function allows writing more than 20 bytes but the generated |
1233 | | * certificates in that case may be rejected by other implementations. |
1234 | | * |
1235 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1236 | | * negative error value. |
1237 | | **/ |
1238 | | int |
1239 | | gnutls_x509_crt_set_serial(gnutls_x509_crt_t cert, const void *serial, |
1240 | | size_t serial_size) |
1241 | 0 | { |
1242 | 0 | int ret; |
1243 | 0 | unsigned all_zero, i; |
1244 | 0 | const unsigned char *pserial = serial; |
1245 | |
|
1246 | 0 | if (cert == NULL) { |
1247 | 0 | gnutls_assert(); |
1248 | 0 | return GNUTLS_E_INVALID_REQUEST; |
1249 | 0 | } |
1250 | | |
1251 | | /* check for non-zero serial */ |
1252 | 0 | all_zero = 1; |
1253 | 0 | for (i = 0; i < serial_size; i++) { |
1254 | 0 | if (pserial[i] != 0) { |
1255 | 0 | all_zero = 0; |
1256 | 0 | break; |
1257 | 0 | } |
1258 | 0 | } |
1259 | |
|
1260 | 0 | if (all_zero) { |
1261 | 0 | _gnutls_debug_log("error: certificate serial is zero\n"); |
1262 | 0 | return GNUTLS_E_INVALID_REQUEST; |
1263 | 0 | } |
1264 | | |
1265 | 0 | MODIFIED(cert); |
1266 | |
|
1267 | 0 | ret = |
1268 | 0 | asn1_write_value(cert->cert, "tbsCertificate.serialNumber", |
1269 | 0 | serial, serial_size); |
1270 | 0 | if (ret != ASN1_SUCCESS) { |
1271 | 0 | gnutls_assert(); |
1272 | 0 | return _gnutls_asn2err(ret); |
1273 | 0 | } |
1274 | | |
1275 | 0 | return 0; |
1276 | |
|
1277 | 0 | } |
1278 | | |
1279 | | /** |
1280 | | * gnutls_x509_crt_set_issuer_unique_id: |
1281 | | * @cert: a certificate of type #gnutls_x509_crt_t |
1282 | | * @id: The unique ID |
1283 | | * @id_size: Holds the size of the unique ID. |
1284 | | * |
1285 | | * This function will set the X.509 certificate's issuer unique ID field. |
1286 | | * |
1287 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1288 | | * negative error value. |
1289 | | * |
1290 | | * Since: 3.4.7 |
1291 | | **/ |
1292 | | int |
1293 | | gnutls_x509_crt_set_issuer_unique_id(gnutls_x509_crt_t cert, const void *id, |
1294 | | size_t id_size) |
1295 | 0 | { |
1296 | 0 | int ret; |
1297 | |
|
1298 | 0 | if (cert == NULL) { |
1299 | 0 | gnutls_assert(); |
1300 | 0 | return GNUTLS_E_INVALID_REQUEST; |
1301 | 0 | } |
1302 | | |
1303 | 0 | MODIFIED(cert); |
1304 | |
|
1305 | 0 | ret = |
1306 | 0 | asn1_write_value(cert->cert, "tbsCertificate.issuerUniqueID", |
1307 | 0 | id, id_size * 8); |
1308 | 0 | if (ret != ASN1_SUCCESS) { |
1309 | 0 | gnutls_assert(); |
1310 | 0 | return _gnutls_asn2err(ret); |
1311 | 0 | } |
1312 | | |
1313 | 0 | return 0; |
1314 | 0 | } |
1315 | | |
1316 | | /** |
1317 | | * gnutls_x509_crt_set_subject_unique_id: |
1318 | | * @cert: a certificate of type #gnutls_x509_crt_t |
1319 | | * @id: The unique ID |
1320 | | * @id_size: Holds the size of the unique ID. |
1321 | | * |
1322 | | * This function will set the X.509 certificate's subject unique ID field. |
1323 | | * |
1324 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1325 | | * negative error value. |
1326 | | * |
1327 | | * Since: 3.4.7 |
1328 | | **/ |
1329 | | int |
1330 | | gnutls_x509_crt_set_subject_unique_id(gnutls_x509_crt_t cert, const void *id, |
1331 | | size_t id_size) |
1332 | 0 | { |
1333 | 0 | int ret; |
1334 | |
|
1335 | 0 | if (cert == NULL) { |
1336 | 0 | gnutls_assert(); |
1337 | 0 | return GNUTLS_E_INVALID_REQUEST; |
1338 | 0 | } |
1339 | | |
1340 | 0 | MODIFIED(cert); |
1341 | |
|
1342 | 0 | ret = |
1343 | 0 | asn1_write_value(cert->cert, "tbsCertificate.subjectUniqueID", |
1344 | 0 | id, id_size * 8); |
1345 | 0 | if (ret != ASN1_SUCCESS) { |
1346 | 0 | gnutls_assert(); |
1347 | 0 | return _gnutls_asn2err(ret); |
1348 | 0 | } |
1349 | | |
1350 | 0 | return 0; |
1351 | 0 | } |
1352 | | |
1353 | | /* If OPTIONAL fields have not been initialized then |
1354 | | * disable them. |
1355 | | */ |
1356 | | static void disable_optional_stuff(gnutls_x509_crt_t cert) |
1357 | 0 | { |
1358 | 0 | asn1_data_node_st n; |
1359 | 0 | asn1_node node; |
1360 | 0 | unsigned remove_subject_unique_id = 1; |
1361 | 0 | unsigned remove_issuer_unique_id = 1; |
1362 | |
|
1363 | 0 | node = asn1_find_node(cert->cert, "tbsCertificate.issuerUniqueID"); |
1364 | 0 | if (node) { |
1365 | 0 | if (asn1_read_node_value(node, &n) == ASN1_SUCCESS |
1366 | 0 | && n.value_len != 0) |
1367 | 0 | remove_issuer_unique_id = 0; |
1368 | 0 | } |
1369 | |
|
1370 | 0 | node = asn1_find_node(cert->cert, "tbsCertificate.subjectUniqueID"); |
1371 | 0 | if (node) { |
1372 | 0 | if (asn1_read_node_value(node, &n) == ASN1_SUCCESS |
1373 | 0 | && n.value_len != 0) |
1374 | 0 | remove_subject_unique_id = 0; |
1375 | 0 | } |
1376 | |
|
1377 | 0 | if (remove_issuer_unique_id) |
1378 | 0 | (void)asn1_write_value(cert->cert, |
1379 | 0 | "tbsCertificate.issuerUniqueID", NULL, |
1380 | 0 | 0); |
1381 | |
|
1382 | 0 | if (remove_subject_unique_id) |
1383 | 0 | (void)asn1_write_value(cert->cert, |
1384 | 0 | "tbsCertificate.subjectUniqueID", NULL, |
1385 | 0 | 0); |
1386 | |
|
1387 | 0 | if (cert->use_extensions == 0) { |
1388 | 0 | _gnutls_debug_log("Disabling X.509 extensions.\n"); |
1389 | 0 | (void)asn1_write_value(cert->cert, "tbsCertificate.extensions", |
1390 | 0 | NULL, 0); |
1391 | 0 | } |
1392 | |
|
1393 | 0 | return; |
1394 | 0 | } |
1395 | | |
1396 | | /** |
1397 | | * gnutls_x509_crt_set_crl_dist_points: |
1398 | | * @crt: a certificate of type #gnutls_x509_crt_t |
1399 | | * @type: is one of the gnutls_x509_subject_alt_name_t enumerations |
1400 | | * @data_string: The data to be set |
1401 | | * @reason_flags: revocation reasons |
1402 | | * |
1403 | | * This function will set the CRL distribution points certificate extension. |
1404 | | * |
1405 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1406 | | * negative error value. |
1407 | | **/ |
1408 | | int |
1409 | | gnutls_x509_crt_set_crl_dist_points(gnutls_x509_crt_t crt, |
1410 | | gnutls_x509_subject_alt_name_t type, |
1411 | | const void *data_string, |
1412 | | unsigned int reason_flags) |
1413 | 0 | { |
1414 | 0 | return gnutls_x509_crt_set_crl_dist_points2(crt, type, data_string, |
1415 | 0 | strlen(data_string), |
1416 | 0 | reason_flags); |
1417 | 0 | } |
1418 | | |
1419 | | /** |
1420 | | * gnutls_x509_crt_set_crl_dist_points2: |
1421 | | * @crt: a certificate of type #gnutls_x509_crt_t |
1422 | | * @type: is one of the gnutls_x509_subject_alt_name_t enumerations |
1423 | | * @data: The data to be set |
1424 | | * @data_size: The data size |
1425 | | * @reason_flags: revocation reasons |
1426 | | * |
1427 | | * This function will set the CRL distribution points certificate extension. |
1428 | | * |
1429 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1430 | | * negative error value. |
1431 | | * |
1432 | | * Since: 2.6.0 |
1433 | | **/ |
1434 | | int |
1435 | | gnutls_x509_crt_set_crl_dist_points2(gnutls_x509_crt_t crt, |
1436 | | gnutls_x509_subject_alt_name_t type, |
1437 | | const void *data, |
1438 | | unsigned int data_size, |
1439 | | unsigned int reason_flags) |
1440 | 0 | { |
1441 | 0 | int ret; |
1442 | 0 | gnutls_datum_t der_data = { NULL, 0 }; |
1443 | 0 | gnutls_datum_t old_der = { NULL, 0 }; |
1444 | 0 | unsigned int critical; |
1445 | 0 | gnutls_x509_crl_dist_points_t cdp = NULL; |
1446 | 0 | gnutls_datum_t san; |
1447 | |
|
1448 | 0 | if (crt == NULL) { |
1449 | 0 | gnutls_assert(); |
1450 | 0 | return GNUTLS_E_INVALID_REQUEST; |
1451 | 0 | } |
1452 | | |
1453 | 0 | ret = gnutls_x509_crl_dist_points_init(&cdp); |
1454 | 0 | if (ret < 0) |
1455 | 0 | return gnutls_assert_val(ret); |
1456 | | |
1457 | | /* Check if the extension already exists. |
1458 | | */ |
1459 | 0 | ret = |
1460 | 0 | _gnutls_x509_crt_get_extension(crt, "2.5.29.31", 0, &old_der, |
1461 | 0 | &critical); |
1462 | |
|
1463 | 0 | if (ret >= 0 && old_der.data != NULL) { |
1464 | 0 | ret = gnutls_x509_ext_import_crl_dist_points(&old_der, cdp, 0); |
1465 | 0 | if (ret < 0) { |
1466 | 0 | gnutls_assert(); |
1467 | 0 | goto cleanup; |
1468 | 0 | } |
1469 | 0 | } |
1470 | | |
1471 | 0 | san.data = (void *)data; |
1472 | 0 | san.size = data_size; |
1473 | 0 | ret = gnutls_x509_crl_dist_points_set(cdp, type, &san, reason_flags); |
1474 | 0 | if (ret < 0) { |
1475 | 0 | gnutls_assert(); |
1476 | 0 | goto cleanup; |
1477 | 0 | } |
1478 | | |
1479 | | /* generate the extension. |
1480 | | */ |
1481 | 0 | ret = gnutls_x509_ext_export_crl_dist_points(cdp, &der_data); |
1482 | 0 | if (ret < 0) { |
1483 | 0 | gnutls_assert(); |
1484 | 0 | goto cleanup; |
1485 | 0 | } |
1486 | | |
1487 | 0 | ret = _gnutls_x509_crt_set_extension(crt, "2.5.29.31", &der_data, 0); |
1488 | |
|
1489 | 0 | if (ret < 0) { |
1490 | 0 | gnutls_assert(); |
1491 | 0 | goto cleanup; |
1492 | 0 | } |
1493 | | |
1494 | 0 | ret = 0; |
1495 | 0 | cleanup: |
1496 | 0 | _gnutls_free_datum(&der_data); |
1497 | 0 | _gnutls_free_datum(&old_der); |
1498 | 0 | if (cdp != NULL) |
1499 | 0 | gnutls_x509_crl_dist_points_deinit(cdp); |
1500 | |
|
1501 | 0 | return ret; |
1502 | |
|
1503 | 0 | } |
1504 | | |
1505 | | /** |
1506 | | * gnutls_x509_crt_cpy_crl_dist_points: |
1507 | | * @dst: a certificate of type #gnutls_x509_crt_t |
1508 | | * @src: the certificate where the dist points will be copied from |
1509 | | * |
1510 | | * This function will copy the CRL distribution points certificate |
1511 | | * extension, from the source to the destination certificate. |
1512 | | * This may be useful to copy from a CA certificate to issued ones. |
1513 | | * |
1514 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1515 | | * negative error value. |
1516 | | **/ |
1517 | | int |
1518 | | gnutls_x509_crt_cpy_crl_dist_points(gnutls_x509_crt_t dst, |
1519 | | gnutls_x509_crt_t src) |
1520 | 0 | { |
1521 | 0 | int result; |
1522 | 0 | gnutls_datum_t der_data; |
1523 | 0 | unsigned int critical; |
1524 | |
|
1525 | 0 | if (dst == NULL || src == NULL) { |
1526 | 0 | gnutls_assert(); |
1527 | 0 | return GNUTLS_E_INVALID_REQUEST; |
1528 | 0 | } |
1529 | | |
1530 | | /* Check if the extension already exists. |
1531 | | */ |
1532 | 0 | result = |
1533 | 0 | _gnutls_x509_crt_get_extension(src, "2.5.29.31", 0, &der_data, |
1534 | 0 | &critical); |
1535 | 0 | if (result < 0) { |
1536 | 0 | gnutls_assert(); |
1537 | 0 | return result; |
1538 | 0 | } |
1539 | | |
1540 | 0 | result = |
1541 | 0 | _gnutls_x509_crt_set_extension(dst, "2.5.29.31", &der_data, |
1542 | 0 | critical); |
1543 | 0 | _gnutls_free_datum(&der_data); |
1544 | |
|
1545 | 0 | if (result < 0) { |
1546 | 0 | gnutls_assert(); |
1547 | 0 | return result; |
1548 | 0 | } |
1549 | | |
1550 | 0 | return 0; |
1551 | 0 | } |
1552 | | |
1553 | | /** |
1554 | | * gnutls_x509_crt_set_subject_key_id: |
1555 | | * @cert: a certificate of type #gnutls_x509_crt_t |
1556 | | * @id: The key ID |
1557 | | * @id_size: Holds the size of the subject key ID field. |
1558 | | * |
1559 | | * This function will set the X.509 certificate's subject key ID |
1560 | | * extension. |
1561 | | * |
1562 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1563 | | * negative error value. |
1564 | | **/ |
1565 | | int |
1566 | | gnutls_x509_crt_set_subject_key_id(gnutls_x509_crt_t cert, |
1567 | | const void *id, size_t id_size) |
1568 | 0 | { |
1569 | 0 | int result; |
1570 | 0 | gnutls_datum_t old_id, der_data; |
1571 | 0 | gnutls_datum_t d_id; |
1572 | 0 | unsigned int critical; |
1573 | |
|
1574 | 0 | if (cert == NULL) { |
1575 | 0 | gnutls_assert(); |
1576 | 0 | return GNUTLS_E_INVALID_REQUEST; |
1577 | 0 | } |
1578 | | |
1579 | | /* Check if the extension already exists. |
1580 | | */ |
1581 | 0 | result = |
1582 | 0 | _gnutls_x509_crt_get_extension(cert, "2.5.29.14", 0, &old_id, |
1583 | 0 | &critical); |
1584 | |
|
1585 | 0 | if (result >= 0) |
1586 | 0 | _gnutls_free_datum(&old_id); |
1587 | 0 | if (result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { |
1588 | 0 | gnutls_assert(); |
1589 | 0 | return GNUTLS_E_INVALID_REQUEST; |
1590 | 0 | } |
1591 | | |
1592 | | /* generate the extension. |
1593 | | */ |
1594 | 0 | d_id.data = (void *)id; |
1595 | 0 | d_id.size = id_size; |
1596 | |
|
1597 | 0 | result = gnutls_x509_ext_export_subject_key_id(&d_id, &der_data); |
1598 | 0 | if (result < 0) { |
1599 | 0 | gnutls_assert(); |
1600 | 0 | return result; |
1601 | 0 | } |
1602 | | |
1603 | 0 | result = |
1604 | 0 | _gnutls_x509_crt_set_extension(cert, "2.5.29.14", &der_data, 0); |
1605 | |
|
1606 | 0 | _gnutls_free_datum(&der_data); |
1607 | |
|
1608 | 0 | if (result < 0) { |
1609 | 0 | gnutls_assert(); |
1610 | 0 | return result; |
1611 | 0 | } |
1612 | | |
1613 | 0 | return 0; |
1614 | 0 | } |
1615 | | |
1616 | | /** |
1617 | | * gnutls_x509_crt_set_authority_key_id: |
1618 | | * @cert: a certificate of type #gnutls_x509_crt_t |
1619 | | * @id: The key ID |
1620 | | * @id_size: Holds the size of the key ID field. |
1621 | | * |
1622 | | * This function will set the X.509 certificate's authority key ID extension. |
1623 | | * Only the keyIdentifier field can be set with this function. |
1624 | | * |
1625 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1626 | | * negative error value. |
1627 | | **/ |
1628 | | int |
1629 | | gnutls_x509_crt_set_authority_key_id(gnutls_x509_crt_t cert, |
1630 | | const void *id, size_t id_size) |
1631 | 0 | { |
1632 | 0 | int result; |
1633 | 0 | gnutls_datum_t old_id, der_data; |
1634 | 0 | unsigned int critical; |
1635 | |
|
1636 | 0 | if (cert == NULL) { |
1637 | 0 | gnutls_assert(); |
1638 | 0 | return GNUTLS_E_INVALID_REQUEST; |
1639 | 0 | } |
1640 | | |
1641 | | /* Check if the extension already exists. |
1642 | | */ |
1643 | 0 | result = |
1644 | 0 | _gnutls_x509_crt_get_extension(cert, "2.5.29.35", 0, &old_id, |
1645 | 0 | &critical); |
1646 | |
|
1647 | 0 | if (result >= 0) |
1648 | 0 | _gnutls_free_datum(&old_id); |
1649 | 0 | if (result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { |
1650 | 0 | gnutls_assert(); |
1651 | 0 | return GNUTLS_E_INVALID_REQUEST; |
1652 | 0 | } |
1653 | | |
1654 | | /* generate the extension. |
1655 | | */ |
1656 | 0 | result = _gnutls_x509_ext_gen_auth_key_id(id, id_size, &der_data); |
1657 | 0 | if (result < 0) { |
1658 | 0 | gnutls_assert(); |
1659 | 0 | return result; |
1660 | 0 | } |
1661 | | |
1662 | 0 | result = |
1663 | 0 | _gnutls_x509_crt_set_extension(cert, "2.5.29.35", &der_data, 0); |
1664 | |
|
1665 | 0 | _gnutls_free_datum(&der_data); |
1666 | |
|
1667 | 0 | if (result < 0) { |
1668 | 0 | gnutls_assert(); |
1669 | 0 | return result; |
1670 | 0 | } |
1671 | | |
1672 | 0 | return 0; |
1673 | 0 | } |
1674 | | |
1675 | | /** |
1676 | | * gnutls_x509_crt_set_key_purpose_oid: |
1677 | | * @cert: a certificate of type #gnutls_x509_crt_t |
1678 | | * @oid: a pointer to a null terminated string that holds the OID |
1679 | | * @critical: Whether this extension will be critical or not |
1680 | | * |
1681 | | * This function will set the key purpose OIDs of the Certificate. |
1682 | | * These are stored in the Extended Key Usage extension (2.5.29.37) |
1683 | | * See the GNUTLS_KP_* definitions for human readable names. |
1684 | | * |
1685 | | * Subsequent calls to this function will append OIDs to the OID list. |
1686 | | * |
1687 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, |
1688 | | * otherwise a negative error code is returned. |
1689 | | **/ |
1690 | | int |
1691 | | gnutls_x509_crt_set_key_purpose_oid(gnutls_x509_crt_t cert, |
1692 | | const void *oid, unsigned int critical) |
1693 | 0 | { |
1694 | 0 | int ret; |
1695 | 0 | gnutls_datum_t old_id = { NULL, 0 }; |
1696 | 0 | gnutls_datum_t der = { NULL, 0 }; |
1697 | 0 | gnutls_x509_key_purposes_t p = NULL; |
1698 | |
|
1699 | 0 | if (cert == NULL) { |
1700 | 0 | gnutls_assert(); |
1701 | 0 | return GNUTLS_E_INVALID_REQUEST; |
1702 | 0 | } |
1703 | | |
1704 | 0 | ret = gnutls_x509_key_purpose_init(&p); |
1705 | 0 | if (ret < 0) |
1706 | 0 | return gnutls_assert_val(ret); |
1707 | | |
1708 | | /* Check if the extension already exists. |
1709 | | */ |
1710 | 0 | ret = |
1711 | 0 | _gnutls_x509_crt_get_extension(cert, "2.5.29.37", 0, &old_id, NULL); |
1712 | |
|
1713 | 0 | if (ret >= 0) { |
1714 | 0 | ret = gnutls_x509_ext_import_key_purposes(&old_id, p, 0); |
1715 | 0 | if (ret < 0) { |
1716 | 0 | gnutls_assert(); |
1717 | 0 | goto cleanup; |
1718 | 0 | } |
1719 | 0 | } |
1720 | | |
1721 | 0 | ret = gnutls_x509_key_purpose_set(p, oid); |
1722 | 0 | if (ret < 0) { |
1723 | 0 | gnutls_assert(); |
1724 | 0 | goto cleanup; |
1725 | 0 | } |
1726 | | |
1727 | 0 | ret = gnutls_x509_ext_export_key_purposes(p, &der); |
1728 | 0 | if (ret < 0) { |
1729 | 0 | gnutls_assert(); |
1730 | 0 | goto cleanup; |
1731 | 0 | } |
1732 | | |
1733 | 0 | ret = _gnutls_x509_crt_set_extension(cert, "2.5.29.37", &der, critical); |
1734 | 0 | if (ret < 0) { |
1735 | 0 | gnutls_assert(); |
1736 | 0 | goto cleanup; |
1737 | 0 | } |
1738 | | |
1739 | 0 | ret = 0; |
1740 | 0 | cleanup: |
1741 | 0 | _gnutls_free_datum(&der); |
1742 | 0 | _gnutls_free_datum(&old_id); |
1743 | 0 | if (p != NULL) |
1744 | 0 | gnutls_x509_key_purpose_deinit(p); |
1745 | |
|
1746 | 0 | return ret; |
1747 | |
|
1748 | 0 | } |
1749 | | |
1750 | | /** |
1751 | | * gnutls_x509_crt_privkey_sign: |
1752 | | * @crt: a certificate of type #gnutls_x509_crt_t |
1753 | | * @issuer: is the certificate of the certificate issuer |
1754 | | * @issuer_key: holds the issuer's private key |
1755 | | * @dig: The message digest to use, %GNUTLS_DIG_SHA256 is a safe choice |
1756 | | * @flags: must be 0 |
1757 | | * |
1758 | | * This function will sign the certificate with the issuer's private key, and |
1759 | | * will copy the issuer's information into the certificate. |
1760 | | * |
1761 | | * This must be the last step in a certificate generation since all |
1762 | | * the previously set parameters are now signed. |
1763 | | * |
1764 | | * A known limitation of this function is, that a newly-signed certificate will not |
1765 | | * be fully functional (e.g., for signature verification), until it |
1766 | | * is exported an re-imported. |
1767 | | * |
1768 | | * After GnuTLS 3.6.1 the value of @dig may be %GNUTLS_DIG_UNKNOWN, |
1769 | | * and in that case, a suitable but reasonable for the key algorithm will be selected. |
1770 | | * |
1771 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1772 | | * negative error value. |
1773 | | **/ |
1774 | | int |
1775 | | gnutls_x509_crt_privkey_sign(gnutls_x509_crt_t crt, |
1776 | | gnutls_x509_crt_t issuer, |
1777 | | gnutls_privkey_t issuer_key, |
1778 | | gnutls_digest_algorithm_t dig, unsigned int flags) |
1779 | 0 | { |
1780 | 0 | int result; |
1781 | |
|
1782 | 0 | if (crt == NULL || issuer == NULL || issuer_key == NULL) { |
1783 | 0 | gnutls_assert(); |
1784 | 0 | return GNUTLS_E_INVALID_REQUEST; |
1785 | 0 | } |
1786 | | |
1787 | 0 | if (dig == 0) { |
1788 | 0 | result = |
1789 | 0 | gnutls_x509_crt_get_preferred_hash_algorithm(issuer, &dig, |
1790 | 0 | NULL); |
1791 | 0 | if (result < 0) |
1792 | 0 | return gnutls_assert_val(result); |
1793 | 0 | } |
1794 | | |
1795 | 0 | MODIFIED(crt); |
1796 | | |
1797 | | /* disable all the unneeded OPTIONAL fields. |
1798 | | */ |
1799 | 0 | disable_optional_stuff(crt); |
1800 | |
|
1801 | 0 | result = _gnutls_check_cert_sanity(crt); |
1802 | 0 | if (result < 0) { |
1803 | 0 | gnutls_assert(); |
1804 | 0 | return result; |
1805 | 0 | } |
1806 | | |
1807 | 0 | result = _gnutls_x509_pkix_sign(crt->cert, "tbsCertificate", |
1808 | 0 | dig, flags, issuer, issuer_key); |
1809 | 0 | if (result < 0) { |
1810 | 0 | gnutls_assert(); |
1811 | 0 | return result; |
1812 | 0 | } |
1813 | | |
1814 | 0 | return 0; |
1815 | 0 | } |
1816 | | |
1817 | | /** |
1818 | | * gnutls_x509_crt_set_authority_info_access: |
1819 | | * @crt: Holds the certificate |
1820 | | * @what: what data to get, a #gnutls_info_access_what_t type. |
1821 | | * @data: output data to be freed with gnutls_free(). |
1822 | | * |
1823 | | * This function sets the Authority Information Access (AIA) |
1824 | | * extension, see RFC 5280 section 4.2.2.1 for more information. |
1825 | | * |
1826 | | * The type of data stored in @data is specified via @what which |
1827 | | * should be #gnutls_info_access_what_t values. |
1828 | | * |
1829 | | * If @what is %GNUTLS_IA_OCSP_URI, @data will hold the OCSP URI. |
1830 | | * If @what is %GNUTLS_IA_CAISSUERS_URI, @data will hold the caIssuers |
1831 | | * URI. |
1832 | | * |
1833 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1834 | | * negative error value. |
1835 | | * |
1836 | | * Since: 3.0 |
1837 | | **/ |
1838 | | int |
1839 | | gnutls_x509_crt_set_authority_info_access(gnutls_x509_crt_t crt, |
1840 | | int what, gnutls_datum_t * data) |
1841 | 0 | { |
1842 | 0 | int ret; |
1843 | 0 | gnutls_datum_t der = { NULL, 0 }; |
1844 | 0 | gnutls_datum_t new_der = { NULL, 0 }; |
1845 | 0 | gnutls_x509_aia_t aia_ctx = NULL; |
1846 | 0 | const char *oid; |
1847 | 0 | unsigned int c; |
1848 | |
|
1849 | 0 | if (crt == NULL) |
1850 | 0 | return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); |
1851 | | |
1852 | 0 | ret = gnutls_x509_aia_init(&aia_ctx); |
1853 | 0 | if (ret < 0) { |
1854 | 0 | gnutls_assert(); |
1855 | 0 | return ret; |
1856 | 0 | } |
1857 | | |
1858 | 0 | ret = _gnutls_x509_crt_get_extension(crt, GNUTLS_OID_AIA, 0, &der, &c); |
1859 | 0 | if (ret >= 0) { /* decode it */ |
1860 | 0 | ret = gnutls_x509_ext_import_aia(&der, aia_ctx, 0); |
1861 | 0 | if (ret < 0) { |
1862 | 0 | gnutls_assert(); |
1863 | 0 | goto cleanup; |
1864 | 0 | } |
1865 | 0 | } |
1866 | | |
1867 | 0 | if (what == GNUTLS_IA_OCSP_URI) |
1868 | 0 | oid = GNUTLS_OID_AD_OCSP; |
1869 | 0 | else if (what == GNUTLS_IA_CAISSUERS_URI) |
1870 | 0 | oid = GNUTLS_OID_AD_CAISSUERS; |
1871 | 0 | else |
1872 | 0 | return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); |
1873 | 0 | ret = gnutls_x509_aia_set(aia_ctx, oid, GNUTLS_SAN_URI, data); |
1874 | 0 | if (ret < 0) { |
1875 | 0 | gnutls_assert(); |
1876 | 0 | goto cleanup; |
1877 | 0 | } |
1878 | | |
1879 | 0 | ret = gnutls_x509_ext_export_aia(aia_ctx, &new_der); |
1880 | 0 | if (ret < 0) { |
1881 | 0 | gnutls_assert(); |
1882 | 0 | goto cleanup; |
1883 | 0 | } |
1884 | | |
1885 | 0 | ret = _gnutls_x509_crt_set_extension(crt, GNUTLS_OID_AIA, &new_der, 0); |
1886 | 0 | if (ret < 0) { |
1887 | 0 | gnutls_assert(); |
1888 | 0 | goto cleanup; |
1889 | 0 | } |
1890 | | |
1891 | 0 | cleanup: |
1892 | 0 | if (aia_ctx != NULL) |
1893 | 0 | gnutls_x509_aia_deinit(aia_ctx); |
1894 | 0 | _gnutls_free_datum(&new_der); |
1895 | 0 | _gnutls_free_datum(&der); |
1896 | |
|
1897 | 0 | return ret; |
1898 | 0 | } |
1899 | | |
1900 | | /** |
1901 | | * gnutls_x509_crt_set_policy: |
1902 | | * @crt: should contain a #gnutls_x509_crt_t type |
1903 | | * @policy: A pointer to a policy |
1904 | | * @critical: use non-zero if the extension is marked as critical |
1905 | | * |
1906 | | * This function will set the certificate policy extension (2.5.29.32). |
1907 | | * Multiple calls to this function append a new policy. |
1908 | | * |
1909 | | * Note the maximum text size for the qualifier %GNUTLS_X509_QUALIFIER_NOTICE |
1910 | | * is 200 characters. This function will fail with %GNUTLS_E_INVALID_REQUEST |
1911 | | * if this is exceeded. |
1912 | | * |
1913 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1914 | | * negative error value. |
1915 | | * |
1916 | | * Since: 3.1.5 |
1917 | | **/ |
1918 | | int |
1919 | | gnutls_x509_crt_set_policy(gnutls_x509_crt_t crt, |
1920 | | const struct gnutls_x509_policy_st *policy, |
1921 | | unsigned int critical) |
1922 | 0 | { |
1923 | 0 | int ret; |
1924 | 0 | gnutls_datum_t der_data = { NULL, 0 }, prev_der_data = { NULL, 0 }; |
1925 | 0 | gnutls_x509_policies_t policies = NULL; |
1926 | |
|
1927 | 0 | if (crt == NULL) { |
1928 | 0 | gnutls_assert(); |
1929 | 0 | return GNUTLS_E_INVALID_REQUEST; |
1930 | 0 | } |
1931 | | |
1932 | 0 | ret = gnutls_x509_policies_init(&policies); |
1933 | 0 | if (ret < 0) { |
1934 | 0 | gnutls_assert(); |
1935 | 0 | return ret; |
1936 | 0 | } |
1937 | | |
1938 | 0 | ret = _gnutls_x509_crt_get_extension(crt, "2.5.29.32", 0, |
1939 | 0 | &prev_der_data, NULL); |
1940 | 0 | if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { |
1941 | 0 | gnutls_assert(); |
1942 | 0 | goto cleanup; |
1943 | 0 | } |
1944 | | |
1945 | 0 | if (ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { |
1946 | 0 | ret = gnutls_x509_ext_import_policies(&prev_der_data, |
1947 | 0 | policies, 0); |
1948 | 0 | if (ret < 0) { |
1949 | 0 | gnutls_assert(); |
1950 | 0 | goto cleanup; |
1951 | 0 | } |
1952 | 0 | } |
1953 | | |
1954 | 0 | ret = gnutls_x509_policies_set(policies, policy); |
1955 | 0 | if (ret < 0) { |
1956 | 0 | gnutls_assert(); |
1957 | 0 | goto cleanup; |
1958 | 0 | } |
1959 | | |
1960 | 0 | ret = gnutls_x509_ext_export_policies(policies, &der_data); |
1961 | 0 | if (ret < 0) { |
1962 | 0 | gnutls_assert(); |
1963 | 0 | goto cleanup; |
1964 | 0 | } |
1965 | | |
1966 | 0 | ret = _gnutls_x509_crt_set_extension(crt, "2.5.29.32", &der_data, 0); |
1967 | |
|
1968 | 0 | cleanup: |
1969 | 0 | if (policies != NULL) |
1970 | 0 | gnutls_x509_policies_deinit(policies); |
1971 | 0 | _gnutls_free_datum(&prev_der_data); |
1972 | 0 | _gnutls_free_datum(&der_data); |
1973 | |
|
1974 | 0 | return ret; |
1975 | 0 | } |
1976 | | |
1977 | | /** |
1978 | | * gnutls_x509_crt_set_spki: |
1979 | | * @crt: a certificate of type #gnutls_x509_crt_t |
1980 | | * @spki: a SubjectPublicKeyInfo structure of type #gnutls_x509_spki_t |
1981 | | * @flags: must be zero |
1982 | | * |
1983 | | * This function will set the certificate's subject public key |
1984 | | * information explicitly. This is intended to be used in the cases |
1985 | | * where a single public key (e.g., RSA) can be used for multiple |
1986 | | * signature algorithms (RSA PKCS1-1.5, and RSA-PSS). |
1987 | | * |
1988 | | * To export the public key (i.e., the SubjectPublicKeyInfo part), check |
1989 | | * gnutls_pubkey_import_x509(). |
1990 | | * |
1991 | | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
1992 | | * negative error value. |
1993 | | * |
1994 | | * Since: 3.6.0 |
1995 | | **/ |
1996 | | int |
1997 | | gnutls_x509_crt_set_spki(gnutls_x509_crt_t crt, |
1998 | | const gnutls_x509_spki_t spki, unsigned int flags) |
1999 | 0 | { |
2000 | 0 | int ret; |
2001 | 0 | gnutls_pk_algorithm_t crt_pk; |
2002 | 0 | gnutls_x509_spki_st tpki; |
2003 | 0 | gnutls_pk_params_st params; |
2004 | 0 | unsigned bits; |
2005 | |
|
2006 | 0 | if (crt == NULL) { |
2007 | 0 | gnutls_assert(); |
2008 | 0 | return GNUTLS_E_INVALID_REQUEST; |
2009 | 0 | } |
2010 | | |
2011 | 0 | ret = _gnutls_x509_crt_get_mpis(crt, ¶ms); |
2012 | 0 | if (ret < 0) { |
2013 | 0 | gnutls_assert(); |
2014 | 0 | return ret; |
2015 | 0 | } |
2016 | | |
2017 | 0 | bits = pubkey_to_bits(¶ms); |
2018 | 0 | crt_pk = params.algo; |
2019 | |
|
2020 | 0 | if (!_gnutls_pk_are_compat(crt_pk, spki->pk)) { |
2021 | 0 | ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); |
2022 | 0 | goto cleanup; |
2023 | 0 | } |
2024 | | |
2025 | 0 | if (spki->pk != GNUTLS_PK_RSA_PSS) { |
2026 | 0 | if (crt_pk == spki->pk) { |
2027 | 0 | ret = 0; |
2028 | 0 | goto cleanup; |
2029 | 0 | } |
2030 | | |
2031 | 0 | gnutls_assert(); |
2032 | 0 | ret = GNUTLS_E_INVALID_REQUEST; |
2033 | 0 | goto cleanup; |
2034 | 0 | } |
2035 | | |
2036 | 0 | memset(&tpki, 0, sizeof(gnutls_x509_spki_st)); |
2037 | |
|
2038 | 0 | if (crt_pk == GNUTLS_PK_RSA) { |
2039 | 0 | const mac_entry_st *me; |
2040 | |
|
2041 | 0 | me = hash_to_entry(spki->rsa_pss_dig); |
2042 | 0 | if (unlikely(me == NULL)) { |
2043 | 0 | gnutls_assert(); |
2044 | 0 | ret = GNUTLS_E_INVALID_REQUEST; |
2045 | 0 | goto cleanup; |
2046 | 0 | } |
2047 | | |
2048 | 0 | tpki.pk = spki->pk; |
2049 | 0 | tpki.rsa_pss_dig = spki->rsa_pss_dig; |
2050 | | |
2051 | | /* If salt size is zero, find the optimal salt size. */ |
2052 | 0 | if (spki->salt_size == 0) { |
2053 | 0 | ret = _gnutls_find_rsa_pss_salt_size(bits, me, |
2054 | 0 | spki->salt_size); |
2055 | 0 | if (ret < 0) { |
2056 | 0 | gnutls_assert(); |
2057 | 0 | goto cleanup; |
2058 | 0 | } |
2059 | 0 | tpki.salt_size = ret; |
2060 | 0 | } else |
2061 | 0 | tpki.salt_size = spki->salt_size; |
2062 | 0 | } else if (crt_pk == GNUTLS_PK_RSA_PSS) { |
2063 | 0 | ret = _gnutls_x509_crt_read_spki_params(crt, &tpki); |
2064 | 0 | if (ret < 0) { |
2065 | 0 | gnutls_assert(); |
2066 | 0 | goto cleanup; |
2067 | 0 | } |
2068 | | |
2069 | 0 | tpki.salt_size = spki->salt_size; |
2070 | 0 | tpki.rsa_pss_dig = spki->rsa_pss_dig; |
2071 | 0 | } |
2072 | | |
2073 | 0 | memcpy(¶ms.spki, &tpki, sizeof(tpki)); |
2074 | 0 | ret = _gnutls_x509_check_pubkey_params(¶ms); |
2075 | 0 | if (ret < 0) { |
2076 | 0 | gnutls_assert(); |
2077 | 0 | goto cleanup; |
2078 | 0 | } |
2079 | | |
2080 | 0 | MODIFIED(crt); |
2081 | |
|
2082 | 0 | ret = _gnutls_x509_write_spki_params(crt->cert, |
2083 | 0 | "tbsCertificate." |
2084 | 0 | "subjectPublicKeyInfo.algorithm", |
2085 | 0 | &tpki); |
2086 | 0 | if (ret < 0) { |
2087 | 0 | gnutls_assert(); |
2088 | 0 | goto cleanup; |
2089 | 0 | } |
2090 | | |
2091 | 0 | ret = 0; |
2092 | 0 | cleanup: |
2093 | 0 | gnutls_pk_params_release(¶ms); |
2094 | 0 | return ret; |
2095 | 0 | } |