3 * @brief Functions to build PKCS#10 requests
5 * Contains functions to build DER encoded pkcs#10 certificate requests
8 /* Copyright (C) 2005 Jan Hutter, Martin Willi
9 * Hochschule fuer Technik Rapperswil
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
29 #include <asn1/asn1.h>
32 #include "../pluto/constants.h"
33 #include "../pluto/defs.h"
34 #include "../pluto/log.h"
35 #include "../pluto/x509.h"
39 /* some pre-coded OIDs */
41 static u_char ASN1_challengePassword_oid_str
[] = {
42 0x06,0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x07
45 static const chunk_t ASN1_challengePassword_oid
= chunk_from_buf(ASN1_challengePassword_oid_str
);
47 static u_char ASN1_extensionRequest_oid_str
[] = {
48 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x0E
51 static const chunk_t ASN1_extensionRequest_oid
= chunk_from_buf(ASN1_extensionRequest_oid_str
);
54 * @brief Adds a subjectAltName in DER-coded form to a linked list
56 * @param[in,out] subjectAltNames head of the linked list of subjectAltNames
57 * @param[in] kind type of the subjectAltName (which is a generalName)
58 * @param[in] value value of the subjectAltName as an ASCII string
61 pkcs10_add_subjectAltName(generalName_t
**subjectAltNames
, generalNames_t kind
65 asn1_t asn1_type
= ASN1_EOC
;
66 chunk_t name
= { value
, strlen(value
) };
71 asn1_type
= ASN1_CONTEXT_S_1
;
74 asn1_type
= ASN1_CONTEXT_S_2
;
80 /* convert an ASCII dotted IPv4 address (e.g. 123.456.78.90)
81 * to a byte representation in network order
83 if (!inet_aton(value
, &addr
))
85 fprintf(stderr
, "error in IPv4 subjectAltName\n");
88 asn1_type
= ASN1_CONTEXT_S_7
;
89 name
.ptr
= (u_char
*) &addr
.s_addr
;
90 name
.len
= sizeof(addr
.s_addr
);
97 gn
= malloc_thing(generalName_t
);
99 gn
->name
= asn1_simple_object(asn1_type
, name
);
100 gn
->next
= *subjectAltNames
;
101 *subjectAltNames
= gn
;
105 * @brief Builds the requestInfoAttributes of the certificationRequestInfo-field
107 * challenge password ans subjectAltNames are only included,
108 * when avaiable in given #pkcs10_t structure
110 * @param[in] pkcs10 Pointer to a #pkcs10_t structure
111 * @return 1 if succeeded, 0 otherwise
114 build_req_info_attributes(pkcs10_t
* pkcs10
)
117 chunk_t subjectAltNames
= chunk_empty
;
118 chunk_t challengePassword
= chunk_empty
;
120 if (pkcs10
->subjectAltNames
!= NULL
)
123 subjectAltNames
= asn1_wrap(ASN1_SEQUENCE
, "cm"
124 , ASN1_extensionRequest_oid
125 , asn1_wrap(ASN1_SET
, "m"
126 , asn1_wrap(ASN1_SEQUENCE
, "m"
127 , build_subjectAltNames(pkcs10
->subjectAltNames
)
133 if (pkcs10
->challengePassword
.len
> 0)
135 asn1_t type
= asn1_is_printablestring(pkcs10
->challengePassword
)
136 ? ASN1_PRINTABLESTRING
: ASN1_T61STRING
;
138 challengePassword
= asn1_wrap(ASN1_SEQUENCE
, "cm"
139 , ASN1_challengePassword_oid
140 , asn1_wrap(ASN1_SET
, "m"
141 , asn1_simple_object(type
, pkcs10
->challengePassword
)
146 return asn1_wrap(ASN1_CONTEXT_C_0
, "mm"
148 , challengePassword
);
152 * @brief Builds a DER-code pkcs#10 certificate request
154 * @param[in] pkcs10 pointer to a pkcs10_t struct
155 * @return DER-code pkcs10 request
158 pkcs10_build_request(pkcs10_t
*pkcs10
, int signature_alg
)
160 chunk_t key
= chunk_empty
;
162 pkcs10
->public_key
->get_encoding(pkcs10
->public_key
, KEY_PUB_ASN1_DER
, &key
);
164 chunk_t keyInfo
= asn1_wrap(ASN1_SEQUENCE
, "cm",
165 asn1_algorithmIdentifier(OID_RSA_ENCRYPTION
),
166 asn1_bitstring("m", key
));
168 chunk_t cert_req_info
= asn1_wrap(ASN1_SEQUENCE
, "ccmm",
172 build_req_info_attributes(pkcs10
));
174 chunk_t signature
= x509_build_signature(cert_req_info
, signature_alg
,
175 pkcs10
->private_key
, TRUE
);
177 return asn1_wrap(ASN1_SEQUENCE
, "mcm",
179 asn1_algorithmIdentifier(signature_alg
),
184 * @brief Creates a pkcs#10 certificate request object
186 * To create a certificate request, the RSA key and the
187 * names to be included as subject in the certificate request
188 * (e.g. commonName, organization) are needed. An optional challenge
189 * password or some subjectAltNames may be included.
191 * @param[in] key rsakey of type #rsakey_t
192 * @param[in] subject DER-coded subject distinguished name
193 * @param[in] challengePassword challenge password or chunk_empty
194 * @param[in] subjectAltNames linked list of subjectAltNames or NULL
195 * @return pointer to a #pkcs10_t object
197 pkcs10_t
* pkcs10_build(private_key_t
*private, public_key_t
*public,
198 chunk_t subject
, chunk_t challengePassword
,
199 generalName_t
*subjectAltNames
, int signature_alg
)
201 pkcs10_t
*pkcs10
= malloc_thing(pkcs10_t
);
203 pkcs10
->subject
= subject
;
204 pkcs10
->private_key
= private;
205 pkcs10
->public_key
= public;
206 pkcs10
->challengePassword
= challengePassword
;
207 pkcs10
->subjectAltNames
= subjectAltNames
;
209 pkcs10
->request
= pkcs10_build_request(pkcs10
, signature_alg
);
214 * @brief Frees the resources used by an #pkcs10_t object
216 * @param[in] pkcs10 #pkcs10_t to free
219 pkcs10_free(pkcs10_t
*pkcs10
)
223 free(pkcs10
->request
.ptr
);