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>
30 #include "../pluto/constants.h"
31 #include "../pluto/defs.h"
32 #include "../pluto/oid.h"
33 #include "../pluto/asn1.h"
34 #include "../pluto/pkcs1.h"
35 #include "../pluto/log.h"
36 #include "../pluto/x509.h"
40 /* some pre-coded OIDs */
42 static u_char ASN1_challengePassword_oid_str
[] = {
43 0x06,0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x07
46 static const chunk_t ASN1_challengePassword_oid
= strchunk(ASN1_challengePassword_oid_str
);
48 static u_char ASN1_extensionRequest_oid_str
[] = {
49 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x0E
52 static const chunk_t ASN1_extensionRequest_oid
= strchunk(ASN1_extensionRequest_oid_str
);
55 * @brief Adds a subjectAltName in DER-coded form to a linked list
57 * @param[in,out] subjectAltNames head of the linked list of subjectAltNames
58 * @param[in] kind type of the subjectAltName (which is a generalName)
59 * @param[in] value value of the subjectAltName as an ASCII string
62 pkcs10_add_subjectAltName(generalName_t
**subjectAltNames
, generalNames_t kind
66 asn1_t asn1_type
= ASN1_EOC
;
67 chunk_t name
= { value
, strlen(value
) };
72 asn1_type
= ASN1_CONTEXT_S_1
;
75 asn1_type
= ASN1_CONTEXT_S_2
;
81 /* convert an ASCII dotted IPv4 address (e.g. 123.456.78.90)
82 * to a byte representation in network order
84 if (!inet_aton(value
, &addr
))
86 fprintf(stderr
, "error in IPv4 subjectAltName\n");
89 asn1_type
= ASN1_CONTEXT_S_7
;
90 name
.ptr
= (u_char
*) &addr
.s_addr
;
91 name
.len
= sizeof(addr
.s_addr
);
98 gn
= alloc_thing(generalName_t
, "subjectAltName");
100 gn
->name
= asn1_simple_object(asn1_type
, name
);
101 gn
->next
= *subjectAltNames
;
102 *subjectAltNames
= gn
;
106 * @brief Builds the requestInfoAttributes of the certificationRequestInfo-field
108 * challenge password ans subjectAltNames are only included,
109 * when avaiable in given #pkcs10_t structure
111 * @param[in] pkcs10 Pointer to a #pkcs10_t structure
112 * @return 1 if succeeded, 0 otherwise
115 build_req_info_attributes(pkcs10_t
* pkcs10
)
118 chunk_t subjectAltNames
= empty_chunk
;
119 chunk_t challengePassword
= empty_chunk
;
121 if (pkcs10
->subjectAltNames
!= NULL
)
124 subjectAltNames
= asn1_wrap(ASN1_SEQUENCE
, "cm"
125 , ASN1_extensionRequest_oid
126 , asn1_wrap(ASN1_SET
, "m"
127 , asn1_wrap(ASN1_SEQUENCE
, "m"
128 , build_subjectAltNames(pkcs10
->subjectAltNames
)
134 if (pkcs10
->challengePassword
.len
> 0)
136 asn1_t type
= is_printablestring(pkcs10
->challengePassword
)
137 ? ASN1_PRINTABLESTRING
: ASN1_T61STRING
;
139 challengePassword
= asn1_wrap(ASN1_SEQUENCE
, "cm"
140 , ASN1_challengePassword_oid
141 , asn1_wrap(ASN1_SET
, "m"
142 , asn1_simple_object(type
, pkcs10
->challengePassword
)
147 return asn1_wrap(ASN1_CONTEXT_C_0
, "mm"
149 , challengePassword
);
153 * @brief Builds a DER-code pkcs#10 certificate request
155 * @param[in] pkcs10 pointer to a pkcs10_t struct
156 * @return DER-code pkcs10 request
159 pkcs10_build_request(pkcs10_t
*pkcs10
, int signature_alg
)
161 RSA_public_key_t
*rsak
= (RSA_public_key_t
*) pkcs10
->private_key
;
163 chunk_t cert_req_info
= asn1_wrap(ASN1_SEQUENCE
, "ccmm"
166 , pkcs1_build_publicKeyInfo(rsak
)
167 , build_req_info_attributes(pkcs10
));
169 chunk_t signature
= pkcs1_build_signature(cert_req_info
170 , signature_alg
, pkcs10
->private_key
, TRUE
);
172 return asn1_wrap(ASN1_SEQUENCE
, "mcm"
174 , asn1_algorithmIdentifier(signature_alg
)
179 * @brief Creates a pkcs#10 certificate request object
181 * To create a certificate request, the RSA key and the
182 * names to be included as subject in the certificate request
183 * (e.g. commonName, organization) are needed. An optional challenge
184 * password or some subjectAltNames may be included.
186 * @param[in] key rsakey of type #rsakey_t
187 * @param[in] subject DER-coded subject distinguished name
188 * @param[in] challengePassword challenge password or empty_chunk
189 * @param[in] subjectAltNames linked list of subjectAltNames or NULL
190 * @return pointer to a #pkcs10_t object
193 pkcs10_build(RSA_private_key_t
*key
, chunk_t subject
, chunk_t challengePassword
194 , generalName_t
*subjectAltNames
, int signature_alg
)
196 pkcs10_t
*pkcs10
= alloc_thing(pkcs10_t
, "pkcs10_t");
198 pkcs10
->subject
= subject
;
199 pkcs10
->private_key
= key
;
200 pkcs10
->challengePassword
= challengePassword
;
201 pkcs10
->subjectAltNames
= subjectAltNames
;
203 pkcs10
->request
= pkcs10_build_request(pkcs10
, signature_alg
);
208 * @brief Frees the resources used by an #pkcs10_t object
210 * @param[in] pkcs10 #pkcs10_t to free
213 pkcs10_free(pkcs10_t
*pkcs10
)
217 freeanychunk(pkcs10
->request
);