removed oid.txt and oid.pl in pluto subdir
[strongswan.git] / src / scepclient / pkcs10.c
1 /**
2 * @file pkcs10.c
3 * @brief Functions to build PKCS#10 requests
4 *
5 * Contains functions to build DER encoded pkcs#10 certificate requests
6 */
7
8 /* Copyright (C) 2005 Jan Hutter, Martin Willi
9 * Hochschule fuer Technik Rapperswil
10 *
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>.
15 *
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
19 * for more details.
20 */
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
27
28 #include <freeswan.h>
29 #include <asn1/oid.h>
30
31 #include "../pluto/constants.h"
32 #include "../pluto/defs.h"
33 #include "../pluto/asn1.h"
34 #include "../pluto/pkcs1.h"
35 #include "../pluto/log.h"
36 #include "../pluto/x509.h"
37
38 #include "pkcs10.h"
39
40 /* some pre-coded OIDs */
41
42 static u_char ASN1_challengePassword_oid_str[] = {
43 0x06,0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x07
44 };
45
46 static const chunk_t ASN1_challengePassword_oid = strchunk(ASN1_challengePassword_oid_str);
47
48 static u_char ASN1_extensionRequest_oid_str[] = {
49 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x0E
50 };
51
52 static const chunk_t ASN1_extensionRequest_oid = strchunk(ASN1_extensionRequest_oid_str);
53
54 /**
55 * @brief Adds a subjectAltName in DER-coded form to a linked list
56 *
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
60 */
61 void
62 pkcs10_add_subjectAltName(generalName_t **subjectAltNames, generalNames_t kind
63 , char *value)
64 {
65 generalName_t *gn;
66 asn1_t asn1_type = ASN1_EOC;
67 chunk_t name = { value, strlen(value) };
68
69 switch (kind)
70 {
71 case GN_RFC822_NAME:
72 asn1_type = ASN1_CONTEXT_S_1;
73 break;
74 case GN_DNS_NAME:
75 asn1_type = ASN1_CONTEXT_S_2;
76 break;
77 case GN_IP_ADDRESS:
78 {
79 struct in_addr addr;
80
81 /* convert an ASCII dotted IPv4 address (e.g. 123.456.78.90)
82 * to a byte representation in network order
83 */
84 if (!inet_aton(value, &addr))
85 {
86 fprintf(stderr, "error in IPv4 subjectAltName\n");
87 return;
88 }
89 asn1_type = ASN1_CONTEXT_S_7;
90 name.ptr = (u_char *) &addr.s_addr;
91 name.len = sizeof(addr.s_addr);
92 break;
93 }
94 default:
95 break;
96 }
97
98 gn = alloc_thing(generalName_t, "subjectAltName");
99 gn->kind = kind;
100 gn->name = asn1_simple_object(asn1_type, name);
101 gn->next = *subjectAltNames;
102 *subjectAltNames = gn;
103 }
104
105 /**
106 * @brief Builds the requestInfoAttributes of the certificationRequestInfo-field
107 *
108 * challenge password ans subjectAltNames are only included,
109 * when avaiable in given #pkcs10_t structure
110 *
111 * @param[in] pkcs10 Pointer to a #pkcs10_t structure
112 * @return 1 if succeeded, 0 otherwise
113 */
114 static chunk_t
115 build_req_info_attributes(pkcs10_t* pkcs10)
116 {
117
118 chunk_t subjectAltNames = empty_chunk;
119 chunk_t challengePassword = empty_chunk;
120
121 if (pkcs10->subjectAltNames != NULL)
122 {
123
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)
129 )
130 )
131 );
132 }
133
134 if (pkcs10->challengePassword.len > 0)
135 {
136 asn1_t type = is_printablestring(pkcs10->challengePassword)
137 ? ASN1_PRINTABLESTRING : ASN1_T61STRING;
138
139 challengePassword = asn1_wrap(ASN1_SEQUENCE, "cm"
140 , ASN1_challengePassword_oid
141 , asn1_wrap(ASN1_SET, "m"
142 , asn1_simple_object(type, pkcs10->challengePassword)
143 )
144 );
145 }
146
147 return asn1_wrap(ASN1_CONTEXT_C_0, "mm"
148 , subjectAltNames
149 , challengePassword);
150 }
151
152 /**
153 * @brief Builds a DER-code pkcs#10 certificate request
154 *
155 * @param[in] pkcs10 pointer to a pkcs10_t struct
156 * @return DER-code pkcs10 request
157 */
158 static chunk_t
159 pkcs10_build_request(pkcs10_t *pkcs10, int signature_alg)
160 {
161 RSA_public_key_t *rsak = (RSA_public_key_t *) pkcs10->private_key;
162
163 chunk_t cert_req_info = asn1_wrap(ASN1_SEQUENCE, "ccmm"
164 , ASN1_INTEGER_0
165 , pkcs10->subject
166 , pkcs1_build_publicKeyInfo(rsak)
167 , build_req_info_attributes(pkcs10));
168
169 chunk_t signature = pkcs1_build_signature(cert_req_info
170 , signature_alg, pkcs10->private_key, TRUE);
171
172 return asn1_wrap(ASN1_SEQUENCE, "mcm"
173 , cert_req_info
174 , asn1_algorithmIdentifier(signature_alg)
175 , signature);
176 }
177
178 /**
179 * @brief Creates a pkcs#10 certificate request object
180 *
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.
185 *
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
191 */
192 pkcs10_t*
193 pkcs10_build(RSA_private_key_t *key, chunk_t subject, chunk_t challengePassword
194 , generalName_t *subjectAltNames, int signature_alg)
195 {
196 pkcs10_t *pkcs10 = alloc_thing(pkcs10_t, "pkcs10_t");
197
198 pkcs10->subject = subject;
199 pkcs10->private_key = key;
200 pkcs10->challengePassword = challengePassword;
201 pkcs10->subjectAltNames = subjectAltNames;
202
203 pkcs10->request = pkcs10_build_request(pkcs10, signature_alg);
204 return pkcs10;
205 }
206
207 /**
208 * @brief Frees the resources used by an #pkcs10_t object
209 *
210 * @param[in] pkcs10 #pkcs10_t to free
211 */
212 void
213 pkcs10_free(pkcs10_t *pkcs10)
214 {
215 if (pkcs10 != NULL)
216 {
217 freeanychunk(pkcs10->request);
218 pfree(pkcs10);
219 }
220 }