767b3acf24b034e2ec31ed449d956869ba3feb39
[strongswan.git] / src / libstrongswan / plugins / pkcs1 / pkcs1_builder.c
1 /*
2 * Copyright (C) 2008-2009 Martin Willi
3 * Copyright (C) 2008 Tobias Brunner
4 * Copyright (C) 2000-2008 Andreas Steffen
5 * Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include "pkcs1_builder.h"
19
20 #include <utils/debug.h>
21 #include <asn1/oid.h>
22 #include <asn1/asn1.h>
23 #include <asn1/asn1_parser.h>
24 #include <credentials/keys/private_key.h>
25
26 /**
27 * ASN.1 definition of a subjectPublicKeyInfo structure
28 */
29 static const asn1Object_t pkinfoObjects[] = {
30 { 0, "subjectPublicKeyInfo",ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
31 { 1, "algorithm", ASN1_EOC, ASN1_RAW }, /* 1 */
32 { 1, "subjectPublicKey", ASN1_BIT_STRING, ASN1_BODY }, /* 2 */
33 { 0, "exit", ASN1_EOC, ASN1_EXIT }
34 };
35 #define PKINFO_SUBJECT_PUBLIC_KEY_ALGORITHM 1
36 #define PKINFO_SUBJECT_PUBLIC_KEY 2
37
38 /**
39 * Load a generic public key from an ASN.1 encoded blob
40 */
41 static public_key_t *parse_public_key(chunk_t blob)
42 {
43 asn1_parser_t *parser;
44 chunk_t object;
45 int objectID;
46 public_key_t *key = NULL;
47 key_type_t type = KEY_ANY;
48
49 parser = asn1_parser_create(pkinfoObjects, blob);
50
51 while (parser->iterate(parser, &objectID, &object))
52 {
53 switch (objectID)
54 {
55 case PKINFO_SUBJECT_PUBLIC_KEY_ALGORITHM:
56 {
57 int oid = asn1_parse_algorithmIdentifier(object,
58 parser->get_level(parser)+1, NULL);
59
60 if (oid == OID_RSA_ENCRYPTION || oid == OID_RSAES_OAEP)
61 {
62 type = KEY_RSA;
63 }
64 else if (oid == OID_EC_PUBLICKEY)
65 {
66 /* Need the whole subjectPublicKeyInfo for EC public keys */
67 key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
68 KEY_ECDSA, BUILD_BLOB_ASN1_DER, blob, BUILD_END);
69 goto end;
70 }
71 else if (oid == OID_BLISS_PUBLICKEY)
72 {
73 /* Need the whole subjectPublicKeyInfo for BLISS public keys */
74 key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
75 KEY_BLISS, BUILD_BLOB_ASN1_DER, blob, BUILD_END);
76 goto end;
77 }
78 else
79 {
80 /* key type not supported */
81 goto end;
82 }
83 break;
84 }
85 case PKINFO_SUBJECT_PUBLIC_KEY:
86 if (object.len > 0 && *object.ptr == 0x00)
87 {
88 /* skip initial bit string octet defining 0 unused bits */
89 object = chunk_skip(object, 1);
90 }
91 DBG2(DBG_ASN, "-- > --");
92 key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, type,
93 BUILD_BLOB_ASN1_DER, object, BUILD_END);
94 DBG2(DBG_ASN, "-- < --");
95 break;
96 }
97 }
98
99 end:
100 parser->destroy(parser);
101 return key;
102 }
103
104 /**
105 * ASN.1 definition of RSApublicKey
106 */
107 static const asn1Object_t pubkeyObjects[] = {
108 { 0, "RSAPublicKey", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
109 { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 1 */
110 { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 2 */
111 { 0, "exit", ASN1_EOC, ASN1_EXIT }
112 };
113 #define PUB_KEY_RSA_PUBLIC_KEY 0
114 #define PUB_KEY_MODULUS 1
115 #define PUB_KEY_EXPONENT 2
116
117 /**
118 * Load a RSA public key from an ASN.1 encoded blob.
119 */
120 static public_key_t *parse_rsa_public_key(chunk_t blob)
121 {
122 chunk_t n, e;
123 asn1_parser_t *parser;
124 chunk_t object;
125 int objectID;
126 bool success = FALSE;
127
128 parser = asn1_parser_create(pubkeyObjects, blob);
129
130 while (parser->iterate(parser, &objectID, &object))
131 {
132 switch (objectID)
133 {
134 case PUB_KEY_MODULUS:
135 n = object;
136 break;
137 case PUB_KEY_EXPONENT:
138 e = object;
139 break;
140 }
141 }
142 success = parser->success(parser);
143 parser->destroy(parser);
144
145 if (!success)
146 {
147 return NULL;
148 }
149 return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
150 BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_END);
151 }
152
153 /**
154 * ASN.1 definition of a PKCS#1 RSA private key
155 */
156 static const asn1Object_t privkeyObjects[] = {
157 { 0, "RSAPrivateKey", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
158 { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
159 { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 2 */
160 { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 3 */
161 { 1, "privateExponent", ASN1_INTEGER, ASN1_BODY }, /* 4 */
162 { 1, "prime1", ASN1_INTEGER, ASN1_BODY }, /* 5 */
163 { 1, "prime2", ASN1_INTEGER, ASN1_BODY }, /* 6 */
164 { 1, "exponent1", ASN1_INTEGER, ASN1_BODY }, /* 7 */
165 { 1, "exponent2", ASN1_INTEGER, ASN1_BODY }, /* 8 */
166 { 1, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 9 */
167 { 1, "otherPrimeInfos", ASN1_SEQUENCE, ASN1_OPT |
168 ASN1_LOOP }, /* 10 */
169 { 2, "otherPrimeInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */
170 { 3, "prime", ASN1_INTEGER, ASN1_BODY }, /* 12 */
171 { 3, "exponent", ASN1_INTEGER, ASN1_BODY }, /* 13 */
172 { 3, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 14 */
173 { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 15 */
174 { 0, "exit", ASN1_EOC, ASN1_EXIT }
175 };
176 #define PRIV_KEY_VERSION 1
177 #define PRIV_KEY_MODULUS 2
178 #define PRIV_KEY_PUB_EXP 3
179 #define PRIV_KEY_PRIV_EXP 4
180 #define PRIV_KEY_PRIME1 5
181 #define PRIV_KEY_PRIME2 6
182 #define PRIV_KEY_EXP1 7
183 #define PRIV_KEY_EXP2 8
184 #define PRIV_KEY_COEFF 9
185
186 /**
187 * Load a RSA private key from a ASN1 encoded blob.
188 */
189 static private_key_t *parse_rsa_private_key(chunk_t blob)
190 {
191 chunk_t n, e, d, p, q, exp1, exp2, coeff;
192 asn1_parser_t *parser;
193 chunk_t object;
194 int objectID ;
195 bool success = FALSE;
196
197 parser = asn1_parser_create(privkeyObjects, blob);
198 parser->set_flags(parser, FALSE, TRUE);
199
200 while (parser->iterate(parser, &objectID, &object))
201 {
202 switch (objectID)
203 {
204 case PRIV_KEY_VERSION:
205 if (object.len > 0 && *object.ptr != 0)
206 {
207 DBG1(DBG_ASN, "PKCS#1 private key format is not version 1");
208 goto end;
209 }
210 break;
211 case PRIV_KEY_MODULUS:
212 n = object;
213 break;
214 case PRIV_KEY_PUB_EXP:
215 e = object;
216 break;
217 case PRIV_KEY_PRIV_EXP:
218 d = object;
219 break;
220 case PRIV_KEY_PRIME1:
221 p = object;
222 break;
223 case PRIV_KEY_PRIME2:
224 q = object;
225 break;
226 case PRIV_KEY_EXP1:
227 exp1 = object;
228 break;
229 case PRIV_KEY_EXP2:
230 exp2 = object;
231 break;
232 case PRIV_KEY_COEFF:
233 coeff = object;
234 break;
235 }
236 }
237 success = parser->success(parser);
238
239 end:
240 parser->destroy(parser);
241 if (!success)
242 {
243 return NULL;
244 }
245 return lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
246 BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_RSA_PRIV_EXP, d,
247 BUILD_RSA_PRIME1, p, BUILD_RSA_PRIME2, q, BUILD_RSA_EXP1, exp1,
248 BUILD_RSA_EXP2, exp2, BUILD_RSA_COEFF, coeff, BUILD_END);
249 }
250
251 /**
252 * See header.
253 */
254 public_key_t *pkcs1_public_key_load(key_type_t type, va_list args)
255 {
256 chunk_t blob = chunk_empty;
257
258 while (TRUE)
259 {
260 switch (va_arg(args, builder_part_t))
261 {
262 case BUILD_BLOB_ASN1_DER:
263 blob = va_arg(args, chunk_t);
264 continue;
265 case BUILD_END:
266 break;
267 default:
268 return NULL;
269 }
270 break;
271 }
272 switch (type)
273 {
274 case KEY_ANY:
275 return parse_public_key(blob);
276 case KEY_RSA:
277 return parse_rsa_public_key(blob);
278 default:
279 return NULL;
280 }
281 }
282
283 /**
284 * See header.
285 */
286 private_key_t *pkcs1_private_key_load(key_type_t type, va_list args)
287 {
288 chunk_t blob = chunk_empty;
289
290 while (TRUE)
291 {
292 switch (va_arg(args, builder_part_t))
293 {
294 case BUILD_BLOB_ASN1_DER:
295 blob = va_arg(args, chunk_t);
296 continue;
297 case BUILD_END:
298 break;
299 default:
300 return NULL;
301 }
302 break;
303 }
304 return parse_rsa_private_key(blob);
305 }
306