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