aboutsummaryrefslogtreecommitdiff
path: root/src/daemon/https/x509/crq.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon/https/x509/crq.c')
-rw-r--r--src/daemon/https/x509/crq.c898
1 files changed, 0 insertions, 898 deletions
diff --git a/src/daemon/https/x509/crq.c b/src/daemon/https/x509/crq.c
deleted file mode 100644
index 88ac349d..00000000
--- a/src/daemon/https/x509/crq.c
+++ /dev/null
@@ -1,898 +0,0 @@
1/*
2 * Copyright (C) 2003, 2004, 2005 Free Software Foundation
3 *
4 * Author: Nikos Mavrogiannopoulos
5 *
6 * This file is part of GNUTLS.
7 *
8 * The GNUTLS library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21 * USA
22 *
23 */
24
25/* This file contains functions to handle PKCS #10 certificate requests.
26 */
27
28#include <gnutls_int.h>
29
30#ifdef ENABLE_PKI
31
32#include <gnutls_datum.h>
33#include <gnutls_global.h>
34#include <gnutls_errors.h>
35#include <common.h>
36#include <gnutls_x509.h>
37#include <x509_b64.h>
38#include <crq.h>
39#include <dn.h>
40#include <mpi.h>
41#include <sign.h>
42#include <extensions.h>
43#include <libtasn1.h>
44
45/**
46 * MHD_gnutls_x509_crq_init - This function initializes a MHD_gnutls_x509_crq_t structure
47 * @crq: The structure to be initialized
48 *
49 * This function will initialize a PKCS10 certificate request structure.
50 *
51 * Returns 0 on success.
52 *
53 **/
54int
55MHD_gnutls_x509_crq_init (MHD_gnutls_x509_crq_t * crq)
56{
57 *crq = MHD_gnutls_calloc (1, sizeof (MHD_gnutls_x509_crq_int));
58
59 if (*crq)
60 {
61 int result = MHD__asn1_create_element (MHD__gnutls_get_pkix (),
62 "PKIX1.pkcs-10-CertificationRequest",
63 &((*crq)->crq));
64 if (result != ASN1_SUCCESS)
65 {
66 MHD_gnutls_assert ();
67 MHD_gnutls_free (*crq);
68 return MHD_gtls_asn2err (result);
69 }
70 return 0; /* success */
71 }
72 return GNUTLS_E_MEMORY_ERROR;
73}
74
75/**
76 * MHD_gnutls_x509_crq_deinit - This function deinitializes memory used by a MHD_gnutls_x509_crq_t structure
77 * @crq: The structure to be initialized
78 *
79 * This function will deinitialize a CRL structure.
80 *
81 **/
82void
83MHD_gnutls_x509_crq_deinit (MHD_gnutls_x509_crq_t crq)
84{
85 if (!crq)
86 return;
87
88 if (crq->crq)
89 MHD__asn1_delete_structure (&crq->crq);
90
91 MHD_gnutls_free (crq);
92}
93
94#define PEM_CRQ "NEW CERTIFICATE REQUEST"
95#define PEM_CRQ2 "CERTIFICATE REQUEST"
96
97/**
98 * MHD_gnutls_x509_crq_import - This function will import a DER or PEM encoded Certificate request
99 * @crq: The structure to store the parsed certificate request.
100 * @data: The DER or PEM encoded certificate.
101 * @format: One of DER or PEM
102 *
103 * This function will convert the given DER or PEM encoded Certificate
104 * to the native MHD_gnutls_x509_crq_t format. The output will be stored in @cert.
105 *
106 * If the Certificate is PEM encoded it should have a header of "NEW CERTIFICATE REQUEST".
107 *
108 * Returns 0 on success.
109 *
110 **/
111int
112MHD_gnutls_x509_crq_import (MHD_gnutls_x509_crq_t crq,
113 const MHD_gnutls_datum_t * data,
114 MHD_gnutls_x509_crt_fmt_t format)
115{
116 int result = 0, need_free = 0;
117 MHD_gnutls_datum_t _data;
118
119 if (crq == NULL)
120 {
121 MHD_gnutls_assert ();
122 return GNUTLS_E_INVALID_REQUEST;
123 }
124
125 _data.data = data->data;
126 _data.size = data->size;
127
128 /* If the Certificate is in PEM format then decode it
129 */
130 if (format == GNUTLS_X509_FMT_PEM)
131 {
132 opaque *out;
133
134 /* Try the first header */
135 result =
136 MHD__gnutls_fbase64_decode (PEM_CRQ, data->data, data->size, &out);
137
138 if (result <= 0) /* Go for the second header */
139 result =
140 MHD__gnutls_fbase64_decode (PEM_CRQ2, data->data, data->size, &out);
141
142 if (result <= 0)
143 {
144 if (result == 0)
145 result = GNUTLS_E_INTERNAL_ERROR;
146 MHD_gnutls_assert ();
147 return result;
148 }
149
150 _data.data = out;
151 _data.size = result;
152
153 need_free = 1;
154 }
155
156 result = MHD__asn1_der_decoding (&crq->crq, _data.data, _data.size, NULL);
157 if (result != ASN1_SUCCESS)
158 {
159 result = MHD_gtls_asn2err (result);
160 MHD_gnutls_assert ();
161 goto cleanup;
162 }
163
164 result = 0;
165
166cleanup:
167 if (need_free)
168 MHD__gnutls_free_datum (&_data);
169 return result;
170}
171
172
173
174/**
175 * MHD_gnutls_x509_crq_get_dn - This function returns the Certificate request subject's distinguished name
176 * @crq: should contain a MHD_gnutls_x509_crq_t structure
177 * @buf: a pointer to a structure to hold the name (may be null)
178 * @sizeof_buf: initially holds the size of @buf
179 *
180 * This function will copy the name of the Certificate request
181 * subject in the provided buffer. The name will be in the form
182 * "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253. The output string
183 * will be ASCII or UTF-8 encoded, depending on the certificate data.
184 *
185 * If @buf is null then only the size will be filled.
186 *
187 * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not
188 * long enough, and in that case the *sizeof_buf will be updated with
189 * the required size. On success 0 is returned.
190 *
191 **/
192int
193MHD_gnutls_x509_crq_get_dn (MHD_gnutls_x509_crq_t crq, char *buf,
194 size_t * sizeof_buf)
195{
196 if (crq == NULL)
197 {
198 MHD_gnutls_assert ();
199 return GNUTLS_E_INVALID_REQUEST;
200 }
201
202 return MHD__gnutls_x509_parse_dn (crq->crq,
203 "certificationRequestInfo.subject.rdnSequence",
204 buf, sizeof_buf);
205}
206
207/**
208 * MHD_gnutls_x509_crq_get_dn_by_oid - This function returns the Certificate request subject's distinguished name
209 * @crq: should contain a MHD_gnutls_x509_crq_t structure
210 * @oid: holds an Object Identified in null terminated string
211 * @indx: In case multiple same OIDs exist in the RDN, this specifies
212 * which to send. Use zero to get the first one.
213 * @raw_flag: If non zero returns the raw DER data of the DN part.
214 * @buf: a pointer to a structure to hold the name (may be null)
215 * @sizeof_buf: initially holds the size of @buf
216 *
217 * This function will extract the part of the name of the Certificate
218 * request subject, specified by the given OID. The output will be
219 * encoded as described in RFC2253. The output string will be ASCII
220 * or UTF-8 encoded, depending on the certificate data.
221 *
222 * Some helper macros with popular OIDs can be found in gnutls/x509.h
223 * If raw flag is zero, this function will only return known OIDs as
224 * text. Other OIDs will be DER encoded, as described in RFC2253 --
225 * in hex format with a '\#' prefix. You can check about known OIDs
226 * using MHD_gnutls_x509_dn_oid_known().
227 *
228 * If @buf is null then only the size will be filled.
229 *
230 * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not
231 * long enough, and in that case the *sizeof_buf will be updated with
232 * the required size. On success 0 is returned.
233 *
234 **/
235int
236MHD_gnutls_x509_crq_get_dn_by_oid (MHD_gnutls_x509_crq_t crq, const char *oid,
237 int indx, unsigned int raw_flag,
238 void *buf, size_t * sizeof_buf)
239{
240 if (crq == NULL)
241 {
242 MHD_gnutls_assert ();
243 return GNUTLS_E_INVALID_REQUEST;
244 }
245
246 return MHD__gnutls_x509_parse_dn_oid (crq->crq,
247 "certificationRequestInfo.subject.rdnSequence",
248 oid, indx, raw_flag, buf, sizeof_buf);
249}
250
251/**
252 * MHD_gnutls_x509_crq_get_dn_oid - This function returns the Certificate request subject's distinguished name OIDs
253 * @crq: should contain a MHD_gnutls_x509_crq_t structure
254 * @indx: Specifies which DN OID to send. Use zero to get the first one.
255 * @oid: a pointer to a structure to hold the name (may be null)
256 * @sizeof_oid: initially holds the size of @oid
257 *
258 * This function will extract the requested OID of the name of the
259 * Certificate request subject, specified by the given index.
260 *
261 * If oid is null then only the size will be filled.
262 *
263 * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not
264 * long enough, and in that case the *sizeof_oid will be updated with
265 * the required size. On success 0 is returned.
266 *
267 **/
268int
269MHD_gnutls_x509_crq_get_dn_oid (MHD_gnutls_x509_crq_t crq,
270 int indx, void *oid, size_t * sizeof_oid)
271{
272 if (crq == NULL)
273 {
274 MHD_gnutls_assert ();
275 return GNUTLS_E_INVALID_REQUEST;
276 }
277
278 return MHD__gnutls_x509_get_dn_oid (crq->crq,
279 "certificationRequestInfo.subject.rdnSequence",
280 indx, oid, sizeof_oid);
281}
282
283/* Parses an Attribute list in the MHD__asn1_struct, and searches for the
284 * given OID. The index indicates the attribute value to be returned.
285 *
286 * If raw==0 only printable data are returned, or GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE.
287 *
288 * MHD__asn1_attr_name must be a string in the form "certificationRequestInfo.attributes"
289 *
290 */
291static int
292parse_attribute (ASN1_TYPE MHD__asn1_struct,
293 const char *attr_name, const char *given_oid, int indx,
294 int raw, char *buf, size_t * sizeof_buf)
295{
296 int k1, result;
297 char tmpbuffer1[MAX_NAME_SIZE];
298 char tmpbuffer3[MAX_NAME_SIZE];
299 char value[200];
300 char oid[128];
301 int len, printable;
302
303 if (*sizeof_buf == 0)
304 {
305 MHD_gnutls_assert ();
306 return GNUTLS_E_INVALID_REQUEST;
307 }
308
309 buf[0] = 0;
310
311 k1 = 0;
312 do
313 {
314
315 k1++;
316 /* create a string like "attribute.?1"
317 */
318 if (attr_name[0] != 0)
319 snprintf (tmpbuffer1, sizeof (tmpbuffer1), "%s.?%u", attr_name, k1);
320 else
321 snprintf (tmpbuffer1, sizeof (tmpbuffer1), "?%u", k1);
322
323 len = sizeof (value) - 1;
324 result =
325 MHD__asn1_read_value (MHD__asn1_struct, tmpbuffer1, value, &len);
326
327 if (result == ASN1_ELEMENT_NOT_FOUND)
328 {
329 MHD_gnutls_assert ();
330 break;
331 }
332
333 if (result != ASN1_VALUE_NOT_FOUND)
334 {
335 MHD_gnutls_assert ();
336 result = MHD_gtls_asn2err (result);
337 goto cleanup;
338 }
339
340 /* Move to the attibute type and values
341 */
342 /* Read the OID
343 */
344 MHD_gtls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer1);
345 MHD_gtls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".type");
346
347 len = sizeof (oid) - 1;
348 result = MHD__asn1_read_value (MHD__asn1_struct, tmpbuffer3, oid, &len);
349
350 if (result == ASN1_ELEMENT_NOT_FOUND)
351 break;
352 else if (result != ASN1_SUCCESS)
353 {
354 MHD_gnutls_assert ();
355 result = MHD_gtls_asn2err (result);
356 goto cleanup;
357 }
358
359 if (strcmp (oid, given_oid) == 0)
360 { /* Found the OID */
361
362 /* Read the Value
363 */
364 snprintf (tmpbuffer3, sizeof (tmpbuffer3), "%s.values.?%u",
365 tmpbuffer1, indx + 1);
366
367 len = sizeof (value) - 1;
368 result =
369 MHD__asn1_read_value (MHD__asn1_struct, tmpbuffer3, value, &len);
370
371 if (result != ASN1_SUCCESS)
372 {
373 MHD_gnutls_assert ();
374 result = MHD_gtls_asn2err (result);
375 goto cleanup;
376 }
377
378 if (raw == 0)
379 {
380 printable = MHD__gnutls_x509_oid_data_printable (oid);
381 if (printable == 1)
382 {
383 if ((result =
384 MHD__gnutls_x509_oid_data2string
385 (oid, value, len, buf, sizeof_buf)) < 0)
386 {
387 MHD_gnutls_assert ();
388 goto cleanup;
389 }
390 return 0;
391 }
392 else
393 {
394 MHD_gnutls_assert ();
395 return GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE;
396 }
397 }
398 else
399 { /* raw!=0 */
400 if (*sizeof_buf > (size_t) len)
401 {
402 *sizeof_buf = len;
403 memcpy (buf, value, len);
404
405 return 0;
406 }
407 else
408 {
409 *sizeof_buf = len;
410 MHD_gnutls_assert ();
411 return GNUTLS_E_SHORT_MEMORY_BUFFER;
412 }
413 }
414 }
415
416 }
417 while (1);
418
419 MHD_gnutls_assert ();
420
421 result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
422
423cleanup:
424 return result;
425}
426
427/**
428 * MHD_gnutls_x509_crq_get_challenge_password - This function will get the challenge password
429 * @crq: should contain a MHD_gnutls_x509_crq_t structure
430 * @pass: will hold a null terminated password
431 * @sizeof_pass: Initially holds the size of @pass.
432 *
433 * This function will return the challenge password in the
434 * request.
435 *
436 * Returns 0 on success.
437 *
438 **/
439int
440MHD_gnutls_x509_crq_get_challenge_password (MHD_gnutls_x509_crq_t crq,
441 char *pass, size_t * sizeof_pass)
442{
443 if (crq == NULL)
444 {
445 MHD_gnutls_assert ();
446 return GNUTLS_E_INVALID_REQUEST;
447 }
448
449 return parse_attribute (crq->crq, "certificationRequestInfo.attributes",
450 "1.2.840.113549.1.9.7", 0, 0, pass, sizeof_pass);
451}
452
453/**
454 * MHD_gnutls_x509_crq_set_attribute_by_oid - This function will set an attribute in the request
455 * @crq: should contain a MHD_gnutls_x509_crq_t structure
456 * @oid: holds an Object Identified in null terminated string
457 * @buf: a pointer to a structure that holds the attribute data
458 * @sizeof_buf: holds the size of @buf
459 *
460 * This function will set the attribute in the certificate request specified
461 * by the given Object ID. The attribute must be be DER encoded.
462 *
463 * Returns 0 on success.
464 *
465 **/
466int
467MHD_gnutls_x509_crq_set_attribute_by_oid (MHD_gnutls_x509_crq_t crq,
468 const char *oid, void *buf,
469 size_t sizeof_buf)
470{
471 int result;
472
473 if (crq == NULL)
474 {
475 MHD_gnutls_assert ();
476 return GNUTLS_E_INVALID_REQUEST;
477 }
478
479 /* Add the attribute.
480 */
481 result =
482 MHD__asn1_write_value (crq->crq, "certificationRequestInfo.attributes",
483 "NEW", 1);
484 if (result != ASN1_SUCCESS)
485 {
486 MHD_gnutls_assert ();
487 return MHD_gtls_asn2err (result);
488 }
489
490 result =
491 MHD__gnutls_x509_encode_and_write_attribute (oid,
492 crq->crq,
493 "certificationRequestInfo.attributes.?LAST",
494 buf, sizeof_buf, 1);
495
496 if (result < 0)
497 {
498 MHD_gnutls_assert ();
499 return result;
500 }
501
502 return 0;
503}
504
505/**
506 * MHD_gnutls_x509_crq_get_attribute_by_oid - This function will get an attribute of the request
507 * @crq: should contain a MHD_gnutls_x509_crq_t structure
508 * @oid: holds an Object Identified in null terminated string
509 * @indx: In case multiple same OIDs exist in the attribute list, this specifies
510 * which to send. Use zero to get the first one.
511 * @buf: a pointer to a structure to hold the attribute data (may be null)
512 * @sizeof_buf: initially holds the size of @buf
513 *
514 * This function will return the attribute in the certificate request specified
515 * by the given Object ID. The attribute will be DER encoded.
516 *
517 * Returns 0 on success.
518 *
519 **/
520int
521MHD_gnutls_x509_crq_get_attribute_by_oid (MHD_gnutls_x509_crq_t crq,
522 const char *oid, int indx,
523 void *buf, size_t * sizeof_buf)
524{
525 if (crq == NULL)
526 {
527 MHD_gnutls_assert ();
528 return GNUTLS_E_INVALID_REQUEST;
529 }
530
531 return parse_attribute (crq->crq, "certificationRequestInfo.attributes",
532 oid, indx, 1, buf, sizeof_buf);
533}
534
535/**
536 * MHD_gnutls_x509_crq_set_dn_by_oid - This function will set the Certificate request subject's distinguished name
537 * @crq: should contain a MHD_gnutls_x509_crq_t structure
538 * @oid: holds an Object Identifier in a null terminated string
539 * @raw_flag: must be 0, or 1 if the data are DER encoded
540 * @data: a pointer to the input data
541 * @sizeof_data: holds the size of @data
542 *
543 * This function will set the part of the name of the Certificate request subject, specified
544 * by the given OID. The input string should be ASCII or UTF-8 encoded.
545 *
546 * Some helper macros with popular OIDs can be found in gnutls/x509.h
547 * With this function you can only set the known OIDs. You can test
548 * for known OIDs using MHD_gnutls_x509_dn_oid_known(). For OIDs that are
549 * not known (by gnutls) you should properly DER encode your data, and
550 * call this function with raw_flag set.
551 *
552 * Returns 0 on success.
553 *
554 **/
555int
556MHD_gnutls_x509_crq_set_dn_by_oid (MHD_gnutls_x509_crq_t crq, const char *oid,
557 unsigned int raw_flag, const void *data,
558 unsigned int sizeof_data)
559{
560 if (sizeof_data == 0 || data == NULL || crq == NULL)
561 {
562 return GNUTLS_E_INVALID_REQUEST;
563 }
564
565 return MHD__gnutls_x509_set_dn_oid (crq->crq,
566 "certificationRequestInfo.subject", oid,
567 raw_flag, data, sizeof_data);
568}
569
570/**
571 * MHD_gnutls_x509_crq_set_version - This function will set the Certificate request version
572 * @crq: should contain a MHD_gnutls_x509_crq_t structure
573 * @version: holds the version number. For v1 Requests must be 1.
574 *
575 * This function will set the version of the certificate request. For
576 * version 1 requests this must be one.
577 *
578 * Returns 0 on success.
579 *
580 **/
581int
582MHD_gnutls_x509_crq_set_version (MHD_gnutls_x509_crq_t crq,
583 unsigned int version)
584{
585 int result;
586 unsigned char null = version;
587
588 if (crq == NULL)
589 {
590 MHD_gnutls_assert ();
591 return GNUTLS_E_INVALID_REQUEST;
592 }
593
594 if (null > 0)
595 null--;
596
597 result =
598 MHD__asn1_write_value (crq->crq, "certificationRequestInfo.version",
599 &null, 1);
600 if (result != ASN1_SUCCESS)
601 {
602 MHD_gnutls_assert ();
603 return MHD_gtls_asn2err (result);
604 }
605
606 return 0;
607}
608
609/**
610 * MHD_gnutls_x509_crq_get_version - This function returns the Certificate request's version number
611 * @crq: should contain a MHD_gnutls_x509_crq_t structure
612 *
613 * This function will return the version of the specified Certificate request.
614 *
615 * Returns a negative value on error.
616 *
617 **/
618int
619MHD_gnutls_x509_crq_get_version (MHD_gnutls_x509_crq_t crq)
620{
621 opaque version[5];
622 int len, result;
623
624 if (crq == NULL)
625 {
626 MHD_gnutls_assert ();
627 return GNUTLS_E_INVALID_REQUEST;
628 }
629
630 len = sizeof (version);
631 if ((result =
632 MHD__asn1_read_value (crq->crq, "certificationRequestInfo.version",
633 version, &len)) != ASN1_SUCCESS)
634 {
635
636 if (result == ASN1_ELEMENT_NOT_FOUND)
637 return 1; /* the DEFAULT version */
638 MHD_gnutls_assert ();
639 return MHD_gtls_asn2err (result);
640 }
641
642 return (int) version[0] + 1;
643}
644
645/**
646 * MHD_gnutls_x509_crq_set_key - This function will associate the Certificate request with a key
647 * @crq: should contain a MHD_gnutls_x509_crq_t structure
648 * @key: holds a private key
649 *
650 * This function will set the public parameters from the given private key to the
651 * request. Only RSA keys are currently supported.
652 *
653 * Returns 0 on success.
654 *
655 **/
656int
657MHD_gnutls_x509_crq_set_key (MHD_gnutls_x509_crq_t crq,
658 MHD_gnutls_x509_privkey_t key)
659{
660 int result;
661
662 if (crq == NULL)
663 {
664 MHD_gnutls_assert ();
665 return GNUTLS_E_INVALID_REQUEST;
666 }
667
668 result = MHD__gnutls_x509_encode_and_copy_PKI_params (crq->crq,
669 "certificationRequestInfo.subjectPKInfo",
670 key->pk_algorithm,
671 key->params,
672 key->params_size);
673
674 if (result < 0)
675 {
676 MHD_gnutls_assert ();
677 return result;
678 }
679
680 return 0;
681}
682
683/**
684 * MHD_gnutls_x509_crq_set_challenge_password - This function will set a challenge password
685 * @crq: should contain a MHD_gnutls_x509_crq_t structure
686 * @pass: holds a null terminated password
687 *
688 * This function will set a challenge password to be used when revoking the request.
689 *
690 * Returns 0 on success.
691 *
692 **/
693int
694MHD_gnutls_x509_crq_set_challenge_password (MHD_gnutls_x509_crq_t crq,
695 const char *pass)
696{
697 int result;
698
699 if (crq == NULL)
700 {
701 MHD_gnutls_assert ();
702 return GNUTLS_E_INVALID_REQUEST;
703 }
704
705 /* Add the attribute.
706 */
707 result =
708 MHD__asn1_write_value (crq->crq, "certificationRequestInfo.attributes",
709 "NEW", 1);
710 if (result != ASN1_SUCCESS)
711 {
712 MHD_gnutls_assert ();
713 return MHD_gtls_asn2err (result);
714 }
715
716 result =
717 MHD__gnutls_x509_encode_and_write_attribute ("1.2.840.113549.1.9.7",
718 crq->crq,
719 "certificationRequestInfo.attributes.?LAST",
720 pass, strlen (pass), 1);
721
722 if (result < 0)
723 {
724 MHD_gnutls_assert ();
725 return result;
726 }
727
728 return 0;
729}
730
731/**
732 * MHD_gnutls_x509_crq_sign2 - This function will sign a Certificate request with a key
733 * @crq: should contain a MHD_gnutls_x509_crq_t structure
734 * @key: holds a private key
735 * @dig: The message digest to use. GNUTLS_DIG_SHA1 is the safe choice unless you know what you're doing.
736 * @flags: must be 0
737 *
738 * This function will sign the certificate request with a private key.
739 * This must be the same key as the one used in MHD_gnutls_x509_crt_set_key() since a
740 * certificate request is self signed.
741 *
742 * This must be the last step in a certificate request generation since all
743 * the previously set parameters are now signed.
744 *
745 * Returns 0 on success.
746 *
747 **/
748int
749MHD_gnutls_x509_crq_sign2 (MHD_gnutls_x509_crq_t crq,
750 MHD_gnutls_x509_privkey_t key,
751 enum MHD_GNUTLS_HashAlgorithm dig,
752 unsigned int flags)
753{
754 int result;
755 MHD_gnutls_datum_t signature;
756
757 if (crq == NULL)
758 {
759 MHD_gnutls_assert ();
760 return GNUTLS_E_INVALID_REQUEST;
761 }
762
763 /* Step 1. Self sign the request.
764 */
765 result =
766 MHD__gnutls_x509_sign_tbs (crq->crq, "certificationRequestInfo",
767 dig, key, &signature);
768
769 if (result < 0)
770 {
771 MHD_gnutls_assert ();
772 return result;
773 }
774
775 /* Step 2. write the signature (bits)
776 */
777 result =
778 MHD__asn1_write_value (crq->crq, "signature", signature.data,
779 signature.size * 8);
780
781 MHD__gnutls_free_datum (&signature);
782
783 if (result != ASN1_SUCCESS)
784 {
785 MHD_gnutls_assert ();
786 return MHD_gtls_asn2err (result);
787 }
788
789 /* Step 3. Write the signatureAlgorithm field.
790 */
791 result = MHD__gnutls_x509_write_sig_params (crq->crq, "signatureAlgorithm",
792 key->pk_algorithm, dig,
793 key->params, key->params_size);
794 if (result < 0)
795 {
796 MHD_gnutls_assert ();
797 return result;
798 }
799
800 return 0;
801}
802
803/**
804 * MHD_gnutls_x509_crq_sign - This function will sign a Certificate request with a key
805 * @crq: should contain a MHD_gnutls_x509_crq_t structure
806 * @key: holds a private key
807 *
808 * This function is the same a MHD_gnutls_x509_crq_sign2() with no flags, and
809 * SHA1 as the hash algorithm.
810 *
811 * Returns 0 on success.
812 *
813 **/
814int
815MHD_gnutls_x509_crq_sign (MHD_gnutls_x509_crq_t crq,
816 MHD_gnutls_x509_privkey_t key)
817{
818 return MHD_gnutls_x509_crq_sign2 (crq, key, MHD_GNUTLS_MAC_SHA1, 0);
819}
820
821/**
822 * MHD_gnutls_x509_crq_export - Export the generated certificate request
823 * @crq: Holds the request
824 * @format: the format of output params. One of PEM or DER.
825 * @output_data: will contain a certificate request PEM or DER encoded
826 * @output_data_size: holds the size of output_data (and will be
827 * replaced by the actual size of parameters)
828 *
829 * This function will export the certificate request to a PKCS10
830 *
831 * If the buffer provided is not long enough to hold the output, then
832 * GNUTLS_E_SHORT_MEMORY_BUFFER will be returned and
833 * *output_data_size will be updated.
834 *
835 * If the structure is PEM encoded, it will have a header of "BEGIN
836 * NEW CERTIFICATE REQUEST".
837 *
838 * Return value: In case of failure a negative value will be
839 * returned, and 0 on success.
840 *
841 **/
842int
843MHD_gnutls_x509_crq_export (MHD_gnutls_x509_crq_t crq,
844 MHD_gnutls_x509_crt_fmt_t format,
845 void *output_data, size_t * output_data_size)
846{
847 if (crq == NULL)
848 {
849 MHD_gnutls_assert ();
850 return GNUTLS_E_INVALID_REQUEST;
851 }
852
853 return MHD__gnutls_x509_export_int (crq->crq, format, PEM_CRQ,
854 output_data, output_data_size);
855}
856
857/**
858 * MHD_gnutls_x509_crq_get_pk_algorithm - This function returns the certificate request's PublicKey algorithm
859 * @crq: should contain a MHD_gnutls_x509_crq_t structure
860 * @bits: if bits is non null it will hold the size of the parameters' in bits
861 *
862 * This function will return the public key algorithm of a PKCS \#10
863 * certificate request.
864 *
865 * If bits is non null, it should have enough size to hold the parameters
866 * size in bits. For RSA the bits returned is the modulus.
867 * For DSA the bits returned are of the public
868 * exponent.
869 *
870 * Returns a member of the enum MHD_GNUTLS_PublicKeyAlgorithm enumeration on success,
871 * or a negative value on error.
872 *
873 **/
874int
875MHD_gnutls_x509_crq_get_pk_algorithm (MHD_gnutls_x509_crq_t crq,
876 unsigned int *bits)
877{
878 int result;
879
880 if (crq == NULL)
881 {
882 MHD_gnutls_assert ();
883 return GNUTLS_E_INVALID_REQUEST;
884 }
885
886 result =
887 MHD__gnutls_x509_get_pk_algorithm (crq->crq,
888 "certificationRequestInfo.subjectPKInfo",
889 bits);
890 if (result < 0)
891 {
892 MHD_gnutls_assert ();
893 }
894
895 return result;
896}
897
898#endif /* ENABLE_PKI */