diff options
Diffstat (limited to 'src/daemon/https/x509/privkey_pkcs8.c')
-rw-r--r-- | src/daemon/https/x509/privkey_pkcs8.c | 984 |
1 files changed, 0 insertions, 984 deletions
diff --git a/src/daemon/https/x509/privkey_pkcs8.c b/src/daemon/https/x509/privkey_pkcs8.c deleted file mode 100644 index 30f2caae..00000000 --- a/src/daemon/https/x509/privkey_pkcs8.c +++ /dev/null | |||
@@ -1,984 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003, 2004, 2005, 2007 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 | #include <gnutls_int.h> | ||
26 | |||
27 | #ifdef ENABLE_PKI | ||
28 | |||
29 | #include <gnutls_datum.h> | ||
30 | #include <gnutls_global.h> | ||
31 | #include <gnutls_errors.h> | ||
32 | #include <gnutls_rsa_export.h> | ||
33 | #include <common.h> | ||
34 | #include <gnutls_x509.h> | ||
35 | #include <x509_b64.h> | ||
36 | #include <x509.h> | ||
37 | #include <pkcs12.h> | ||
38 | #include <dn.h> | ||
39 | #include <privkey.h> | ||
40 | #include <extensions.h> | ||
41 | #include <mpi.h> | ||
42 | #include <gnutls_algorithms.h> | ||
43 | #include <gnutls_num.h> | ||
44 | #include "gc.h" | ||
45 | |||
46 | #define PBES2_OID "1.2.840.113549.1.5.13" | ||
47 | #define PBKDF2_OID "1.2.840.113549.1.5.12" | ||
48 | #define DES_EDE3_CBC_OID "1.2.840.113549.3.7" | ||
49 | #define DES_CBC_OID "1.3.14.3.2.7" | ||
50 | |||
51 | /* oid_pbeWithSHAAnd3_KeyTripleDES_CBC */ | ||
52 | #define PKCS12_PBE_3DES_SHA1_OID "1.2.840.113549.1.12.1.3" | ||
53 | #define PKCS12_PBE_ARCFOUR_SHA1_OID "1.2.840.113549.1.12.1.1" | ||
54 | #define PKCS12_PBE_RC2_40_SHA1_OID "1.2.840.113549.1.12.1.6" | ||
55 | |||
56 | struct pbkdf2_params | ||
57 | { | ||
58 | opaque salt[32]; | ||
59 | int salt_size; | ||
60 | unsigned int iter_count; | ||
61 | unsigned int key_size; | ||
62 | }; | ||
63 | |||
64 | struct pbe_enc_params | ||
65 | { | ||
66 | enum MHD_GNUTLS_CipherAlgorithm cipher; | ||
67 | opaque iv[8]; | ||
68 | int iv_size; | ||
69 | }; | ||
70 | |||
71 | static int read_pbkdf2_params (ASN1_TYPE pbes2_asn, | ||
72 | const MHD_gnutls_datum_t * der, | ||
73 | struct pbkdf2_params *params); | ||
74 | static int read_pbe_enc_params (ASN1_TYPE pbes2_asn, | ||
75 | const MHD_gnutls_datum_t * der, | ||
76 | struct pbe_enc_params *params); | ||
77 | static int decrypt_data (schema_id, ASN1_TYPE pkcs8_asn, const char *root, | ||
78 | const char *password, | ||
79 | const struct pbkdf2_params *kdf_params, | ||
80 | const struct pbe_enc_params *enc_params, | ||
81 | MHD_gnutls_datum_t * decrypted_data); | ||
82 | static int decode_private_key_info (const MHD_gnutls_datum_t * der, | ||
83 | MHD_gnutls_x509_privkey_t pkey); | ||
84 | static int readMHD_pkcs12_kdf_params (ASN1_TYPE pbes2_asn, | ||
85 | struct pbkdf2_params *params); | ||
86 | |||
87 | #define PEM_PKCS8 "ENCRYPTED PRIVATE KEY" | ||
88 | #define PEM_UNENCRYPTED_PKCS8 "PRIVATE KEY" | ||
89 | |||
90 | /* Returns a negative error code if the encryption schema in | ||
91 | * the OID is not supported. The schema ID is returned. | ||
92 | */ | ||
93 | static int | ||
94 | check_schema (const char *oid) | ||
95 | { | ||
96 | |||
97 | if (strcmp (oid, PBES2_OID) == 0) | ||
98 | return PBES2; | ||
99 | |||
100 | if (strcmp (oid, PKCS12_PBE_3DES_SHA1_OID) == 0) | ||
101 | return PKCS12_3DES_SHA1; | ||
102 | |||
103 | if (strcmp (oid, PKCS12_PBE_ARCFOUR_SHA1_OID) == 0) | ||
104 | return PKCS12_ARCFOUR_SHA1; | ||
105 | |||
106 | if (strcmp (oid, PKCS12_PBE_RC2_40_SHA1_OID) == 0) | ||
107 | return PKCS12_RC2_40_SHA1; | ||
108 | |||
109 | MHD__gnutls_x509_log ("PKCS encryption schema OID '%s' is unsupported.\n", | ||
110 | oid); | ||
111 | |||
112 | return GNUTLS_E_UNKNOWN_CIPHER_TYPE; | ||
113 | } | ||
114 | |||
115 | /* Read the parameters cipher, IV, salt etc using the given | ||
116 | * schema ID. | ||
117 | */ | ||
118 | static int | ||
119 | read_pkcs_schema_params (schema_id schema, const char *password, | ||
120 | const opaque * data, int data_size, | ||
121 | struct pbkdf2_params *kdf_params, | ||
122 | struct pbe_enc_params *enc_params) | ||
123 | { | ||
124 | ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY; | ||
125 | int result; | ||
126 | MHD_gnutls_datum_t tmp; | ||
127 | |||
128 | switch (schema) | ||
129 | { | ||
130 | |||
131 | case PBES2: | ||
132 | |||
133 | /* Now check the key derivation and the encryption | ||
134 | * functions. | ||
135 | */ | ||
136 | if ((result = | ||
137 | MHD__asn1_create_element (MHD__gnutls_get_pkix (), | ||
138 | "PKIX1.pkcs-5-PBES2-params", | ||
139 | &pbes2_asn)) != ASN1_SUCCESS) | ||
140 | { | ||
141 | MHD_gnutls_assert (); | ||
142 | result = MHD_gtls_asn2err (result); | ||
143 | goto error; | ||
144 | } | ||
145 | |||
146 | /* Decode the parameters. | ||
147 | */ | ||
148 | result = MHD__asn1_der_decoding (&pbes2_asn, data, data_size, NULL); | ||
149 | if (result != ASN1_SUCCESS) | ||
150 | { | ||
151 | MHD_gnutls_assert (); | ||
152 | result = MHD_gtls_asn2err (result); | ||
153 | goto error; | ||
154 | } | ||
155 | |||
156 | tmp.data = (opaque *) data; | ||
157 | tmp.size = data_size; | ||
158 | |||
159 | result = read_pbkdf2_params (pbes2_asn, &tmp, kdf_params); | ||
160 | if (result < 0) | ||
161 | { | ||
162 | MHD_gnutls_assert (); | ||
163 | result = MHD_gtls_asn2err (result); | ||
164 | goto error; | ||
165 | } | ||
166 | |||
167 | result = read_pbe_enc_params (pbes2_asn, &tmp, enc_params); | ||
168 | if (result < 0) | ||
169 | { | ||
170 | MHD_gnutls_assert (); | ||
171 | result = MHD_gtls_asn2err (result); | ||
172 | goto error; | ||
173 | } | ||
174 | |||
175 | MHD__asn1_delete_structure (&pbes2_asn); | ||
176 | return 0; | ||
177 | break; | ||
178 | |||
179 | case PKCS12_3DES_SHA1: | ||
180 | case PKCS12_ARCFOUR_SHA1: | ||
181 | case PKCS12_RC2_40_SHA1: | ||
182 | |||
183 | if ((schema) == PKCS12_3DES_SHA1) | ||
184 | { | ||
185 | enc_params->cipher = MHD_GNUTLS_CIPHER_3DES_CBC; | ||
186 | enc_params->iv_size = 8; | ||
187 | } | ||
188 | else if ((schema) == PKCS12_ARCFOUR_SHA1) | ||
189 | { | ||
190 | enc_params->cipher = MHD_GNUTLS_CIPHER_ARCFOUR_128; | ||
191 | enc_params->iv_size = 0; | ||
192 | } | ||
193 | else if ((schema) == PKCS12_RC2_40_SHA1) | ||
194 | { | ||
195 | enc_params->cipher = MHD_GNUTLS_CIPHER_RC2_40_CBC; | ||
196 | enc_params->iv_size = 8; | ||
197 | } | ||
198 | |||
199 | if ((result = | ||
200 | MHD__asn1_create_element (MHD__gnutls_get_pkix (), | ||
201 | "PKIX1.pkcs-12-PbeParams", | ||
202 | &pbes2_asn)) != ASN1_SUCCESS) | ||
203 | { | ||
204 | MHD_gnutls_assert (); | ||
205 | result = MHD_gtls_asn2err (result); | ||
206 | goto error; | ||
207 | } | ||
208 | |||
209 | /* Decode the parameters. | ||
210 | */ | ||
211 | result = MHD__asn1_der_decoding (&pbes2_asn, data, data_size, NULL); | ||
212 | if (result != ASN1_SUCCESS) | ||
213 | { | ||
214 | MHD_gnutls_assert (); | ||
215 | result = MHD_gtls_asn2err (result); | ||
216 | goto error; | ||
217 | } | ||
218 | |||
219 | result = readMHD_pkcs12_kdf_params (pbes2_asn, kdf_params); | ||
220 | if (result < 0) | ||
221 | { | ||
222 | MHD_gnutls_assert (); | ||
223 | goto error; | ||
224 | } | ||
225 | |||
226 | if (enc_params->iv_size) | ||
227 | { | ||
228 | result = | ||
229 | MHD_pkcs12_string_to_key (2 /*IV*/, kdf_params->salt, | ||
230 | kdf_params->salt_size, | ||
231 | kdf_params->iter_count, password, | ||
232 | enc_params->iv_size, enc_params->iv); | ||
233 | if (result < 0) | ||
234 | { | ||
235 | MHD_gnutls_assert (); | ||
236 | goto error; | ||
237 | } | ||
238 | |||
239 | } | ||
240 | |||
241 | MHD__asn1_delete_structure (&pbes2_asn); | ||
242 | |||
243 | return 0; | ||
244 | break; | ||
245 | |||
246 | } /* switch */ | ||
247 | |||
248 | return GNUTLS_E_UNKNOWN_CIPHER_TYPE; | ||
249 | |||
250 | error: | ||
251 | MHD__asn1_delete_structure (&pbes2_asn); | ||
252 | return result; | ||
253 | } | ||
254 | |||
255 | /* Converts a PKCS #8 key to | ||
256 | * an internal structure (MHD_gnutls_private_key) | ||
257 | * (normally a PKCS #1 encoded RSA key) | ||
258 | */ | ||
259 | static int | ||
260 | decode_pkcs8_key (const MHD_gnutls_datum_t * raw_key, | ||
261 | const char *password, MHD_gnutls_x509_privkey_t pkey) | ||
262 | { | ||
263 | int result, len; | ||
264 | char enc_oid[64]; | ||
265 | MHD_gnutls_datum_t tmp; | ||
266 | ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY, pkcs8_asn = ASN1_TYPE_EMPTY; | ||
267 | int params_start, params_end, params_len; | ||
268 | struct pbkdf2_params kdf_params; | ||
269 | struct pbe_enc_params enc_params; | ||
270 | schema_id schema; | ||
271 | |||
272 | if ((result = | ||
273 | MHD__asn1_create_element (MHD__gnutls_get_pkix (), | ||
274 | "PKIX1.pkcs-8-EncryptedPrivateKeyInfo", | ||
275 | &pkcs8_asn)) != ASN1_SUCCESS) | ||
276 | { | ||
277 | MHD_gnutls_assert (); | ||
278 | result = MHD_gtls_asn2err (result); | ||
279 | goto error; | ||
280 | } | ||
281 | |||
282 | result = | ||
283 | MHD__asn1_der_decoding (&pkcs8_asn, raw_key->data, raw_key->size, NULL); | ||
284 | if (result != ASN1_SUCCESS) | ||
285 | { | ||
286 | MHD_gnutls_assert (); | ||
287 | result = MHD_gtls_asn2err (result); | ||
288 | goto error; | ||
289 | } | ||
290 | |||
291 | /* Check the encryption schema OID | ||
292 | */ | ||
293 | len = sizeof (enc_oid); | ||
294 | result = | ||
295 | MHD__asn1_read_value (pkcs8_asn, "encryptionAlgorithm.algorithm", | ||
296 | enc_oid, &len); | ||
297 | if (result != ASN1_SUCCESS) | ||
298 | { | ||
299 | MHD_gnutls_assert (); | ||
300 | goto error; | ||
301 | } | ||
302 | |||
303 | if ((result = check_schema (enc_oid)) < 0) | ||
304 | { | ||
305 | MHD_gnutls_assert (); | ||
306 | goto error; | ||
307 | } | ||
308 | |||
309 | schema = result; | ||
310 | |||
311 | /* Get the DER encoding of the parameters. | ||
312 | */ | ||
313 | result = | ||
314 | MHD__asn1_der_decoding_startEnd (pkcs8_asn, raw_key->data, | ||
315 | raw_key->size, | ||
316 | "encryptionAlgorithm.parameters", | ||
317 | ¶ms_start, ¶ms_end); | ||
318 | if (result != ASN1_SUCCESS) | ||
319 | { | ||
320 | MHD_gnutls_assert (); | ||
321 | result = MHD_gtls_asn2err (result); | ||
322 | goto error; | ||
323 | } | ||
324 | params_len = params_end - params_start + 1; | ||
325 | |||
326 | result = | ||
327 | read_pkcs_schema_params (schema, password, | ||
328 | &raw_key->data[params_start], | ||
329 | params_len, &kdf_params, &enc_params); | ||
330 | |||
331 | /* Parameters have been decoded. Now | ||
332 | * decrypt the EncryptedData. | ||
333 | */ | ||
334 | result = | ||
335 | decrypt_data (schema, pkcs8_asn, "encryptedData", password, | ||
336 | &kdf_params, &enc_params, &tmp); | ||
337 | if (result < 0) | ||
338 | { | ||
339 | MHD_gnutls_assert (); | ||
340 | goto error; | ||
341 | } | ||
342 | |||
343 | MHD__asn1_delete_structure (&pkcs8_asn); | ||
344 | |||
345 | result = decode_private_key_info (&tmp, pkey); | ||
346 | MHD__gnutls_free_datum (&tmp); | ||
347 | |||
348 | if (result < 0) | ||
349 | { | ||
350 | /* We've gotten this far. In the real world it's almost certain | ||
351 | * that we're dealing with a good file, but wrong password. | ||
352 | * Sadly like 90% of random data is somehow valid DER for the | ||
353 | * a first small number of bytes, so no easy way to guarantee. */ | ||
354 | if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND || | ||
355 | result == GNUTLS_E_ASN1_IDENTIFIER_NOT_FOUND || | ||
356 | result == GNUTLS_E_ASN1_DER_ERROR || | ||
357 | result == GNUTLS_E_ASN1_VALUE_NOT_FOUND || | ||
358 | result == GNUTLS_E_ASN1_GENERIC_ERROR || | ||
359 | result == GNUTLS_E_ASN1_VALUE_NOT_VALID || | ||
360 | result == GNUTLS_E_ASN1_TAG_ERROR || | ||
361 | result == GNUTLS_E_ASN1_TAG_IMPLICIT || | ||
362 | result == GNUTLS_E_ASN1_TYPE_ANY_ERROR || | ||
363 | result == GNUTLS_E_ASN1_SYNTAX_ERROR || | ||
364 | result == GNUTLS_E_ASN1_DER_OVERFLOW) | ||
365 | { | ||
366 | result = GNUTLS_E_DECRYPTION_FAILED; | ||
367 | } | ||
368 | |||
369 | MHD_gnutls_assert (); | ||
370 | goto error; | ||
371 | } | ||
372 | |||
373 | return 0; | ||
374 | |||
375 | error: | ||
376 | MHD__asn1_delete_structure (&pbes2_asn); | ||
377 | MHD__asn1_delete_structure (&pkcs8_asn); | ||
378 | return result; | ||
379 | } | ||
380 | |||
381 | /* Decodes an RSA privateKey from a PKCS8 structure. | ||
382 | */ | ||
383 | static int | ||
384 | _decode_pkcs8_rsa_key (ASN1_TYPE pkcs8_asn, MHD_gnutls_x509_privkey_t pkey) | ||
385 | { | ||
386 | int ret; | ||
387 | MHD_gnutls_datum_t tmp; | ||
388 | |||
389 | ret = MHD__gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp, 0); | ||
390 | if (ret < 0) | ||
391 | { | ||
392 | MHD_gnutls_assert (); | ||
393 | goto error; | ||
394 | } | ||
395 | |||
396 | pkey->key = MHD__gnutls_privkey_decode_pkcs1_rsa_key (&tmp, pkey); | ||
397 | MHD__gnutls_free_datum (&tmp); | ||
398 | if (pkey->key == NULL) | ||
399 | { | ||
400 | MHD_gnutls_assert (); | ||
401 | goto error; | ||
402 | } | ||
403 | |||
404 | return 0; | ||
405 | |||
406 | error: | ||
407 | MHD_gnutls_x509_privkey_deinit (pkey); | ||
408 | return ret; | ||
409 | } | ||
410 | |||
411 | static int | ||
412 | decode_private_key_info (const MHD_gnutls_datum_t * der, | ||
413 | MHD_gnutls_x509_privkey_t pkey) | ||
414 | { | ||
415 | int result, len; | ||
416 | opaque oid[64]; | ||
417 | ASN1_TYPE pkcs8_asn = ASN1_TYPE_EMPTY; | ||
418 | |||
419 | if ((result = | ||
420 | MHD__asn1_create_element (MHD__gnutls_get_pkix (), | ||
421 | "PKIX1.pkcs-8-PrivateKeyInfo", | ||
422 | &pkcs8_asn)) != ASN1_SUCCESS) | ||
423 | { | ||
424 | MHD_gnutls_assert (); | ||
425 | result = MHD_gtls_asn2err (result); | ||
426 | goto error; | ||
427 | } | ||
428 | |||
429 | result = MHD__asn1_der_decoding (&pkcs8_asn, der->data, der->size, NULL); | ||
430 | if (result != ASN1_SUCCESS) | ||
431 | { | ||
432 | MHD_gnutls_assert (); | ||
433 | result = MHD_gtls_asn2err (result); | ||
434 | goto error; | ||
435 | } | ||
436 | |||
437 | /* Check the private key algorithm OID | ||
438 | */ | ||
439 | len = sizeof (oid); | ||
440 | result = | ||
441 | MHD__asn1_read_value (pkcs8_asn, "privateKeyAlgorithm.algorithm", oid, | ||
442 | &len); | ||
443 | if (result != ASN1_SUCCESS) | ||
444 | { | ||
445 | MHD_gnutls_assert (); | ||
446 | result = MHD_gtls_asn2err (result); | ||
447 | goto error; | ||
448 | } | ||
449 | |||
450 | /* we only support RSA and DSA private keys. | ||
451 | */ | ||
452 | if (strcmp ((const char *) oid, PK_PKIX1_RSA_OID) == 0) | ||
453 | pkey->pk_algorithm = MHD_GNUTLS_PK_RSA; | ||
454 | else | ||
455 | { | ||
456 | MHD_gnutls_assert (); | ||
457 | MHD__gnutls_x509_log | ||
458 | ("PKCS #8 private key OID '%s' is unsupported.\n", oid); | ||
459 | result = GNUTLS_E_UNKNOWN_PK_ALGORITHM; | ||
460 | goto error; | ||
461 | } | ||
462 | |||
463 | /* Get the DER encoding of the actual private key. | ||
464 | */ | ||
465 | |||
466 | if (pkey->pk_algorithm == MHD_GNUTLS_PK_RSA) | ||
467 | result = _decode_pkcs8_rsa_key (pkcs8_asn, pkey); | ||
468 | if (result < 0) | ||
469 | { | ||
470 | MHD_gnutls_assert (); | ||
471 | return result; | ||
472 | } | ||
473 | |||
474 | result = 0; | ||
475 | |||
476 | error: | ||
477 | MHD__asn1_delete_structure (&pkcs8_asn); | ||
478 | |||
479 | return result; | ||
480 | |||
481 | } | ||
482 | |||
483 | /** | ||
484 | * MHD_gnutls_x509_privkey_import_pkcs8 - This function will import a DER or PEM PKCS8 encoded key | ||
485 | * @key: The structure to store the parsed key | ||
486 | * @data: The DER or PEM encoded key. | ||
487 | * @format: One of DER or PEM | ||
488 | * @password: the password to decrypt the key (if it is encrypted). | ||
489 | * @flags: 0 if encrypted or GNUTLS_PKCS_PLAIN if not encrypted. | ||
490 | * | ||
491 | * This function will convert the given DER or PEM encoded PKCS8 2.0 encrypted key | ||
492 | * to the native MHD_gnutls_x509_privkey_t format. The output will be stored in @key. | ||
493 | * Both RSA and DSA keys can be imported, and flags can only be used to indicate | ||
494 | * an unencrypted key. | ||
495 | * | ||
496 | * The @password can be either ASCII or UTF-8 in the default PBES2 | ||
497 | * encryption schemas, or ASCII for the PKCS12 schemas. | ||
498 | * | ||
499 | * If the Certificate is PEM encoded it should have a header of "ENCRYPTED PRIVATE KEY", | ||
500 | * or "PRIVATE KEY". You only need to specify the flags if the key is DER encoded, since | ||
501 | * in that case the encryption status cannot be auto-detected. | ||
502 | * | ||
503 | * Returns 0 on success. | ||
504 | * | ||
505 | **/ | ||
506 | int | ||
507 | MHD_gnutls_x509_privkey_import_pkcs8 (MHD_gnutls_x509_privkey_t key, | ||
508 | const MHD_gnutls_datum_t * data, | ||
509 | MHD_gnutls_x509_crt_fmt_t format, | ||
510 | const char *password, | ||
511 | unsigned int flags) | ||
512 | { | ||
513 | int result = 0, need_free = 0; | ||
514 | MHD_gnutls_datum_t _data; | ||
515 | |||
516 | if (key == NULL) | ||
517 | { | ||
518 | MHD_gnutls_assert (); | ||
519 | return GNUTLS_E_INVALID_REQUEST; | ||
520 | } | ||
521 | |||
522 | _data.data = data->data; | ||
523 | _data.size = data->size; | ||
524 | |||
525 | key->pk_algorithm = MHD_GNUTLS_PK_UNKNOWN; | ||
526 | |||
527 | /* If the Certificate is in PEM format then decode it | ||
528 | */ | ||
529 | if (format == GNUTLS_X509_FMT_PEM) | ||
530 | { | ||
531 | opaque *out; | ||
532 | |||
533 | /* Try the first header | ||
534 | */ | ||
535 | result = | ||
536 | MHD__gnutls_fbase64_decode (PEM_UNENCRYPTED_PKCS8, | ||
537 | data->data, data->size, &out); | ||
538 | |||
539 | if (result < 0) | ||
540 | { /* Try the encrypted header | ||
541 | */ | ||
542 | result = | ||
543 | MHD__gnutls_fbase64_decode (PEM_PKCS8, data->data, data->size, | ||
544 | &out); | ||
545 | |||
546 | if (result <= 0) | ||
547 | { | ||
548 | if (result == 0) | ||
549 | result = GNUTLS_E_INTERNAL_ERROR; | ||
550 | MHD_gnutls_assert (); | ||
551 | return result; | ||
552 | } | ||
553 | } | ||
554 | else if (flags == 0) | ||
555 | flags |= GNUTLS_PKCS_PLAIN; | ||
556 | |||
557 | _data.data = out; | ||
558 | _data.size = result; | ||
559 | |||
560 | need_free = 1; | ||
561 | } | ||
562 | |||
563 | if (flags & GNUTLS_PKCS_PLAIN) | ||
564 | { | ||
565 | result = decode_private_key_info (&_data, key); | ||
566 | } | ||
567 | else | ||
568 | { /* encrypted. */ | ||
569 | result = decode_pkcs8_key (&_data, password, key); | ||
570 | } | ||
571 | |||
572 | if (result < 0) | ||
573 | { | ||
574 | MHD_gnutls_assert (); | ||
575 | goto cleanup; | ||
576 | } | ||
577 | |||
578 | if (need_free) | ||
579 | MHD__gnutls_free_datum (&_data); | ||
580 | |||
581 | /* The key has now been decoded. | ||
582 | */ | ||
583 | |||
584 | return 0; | ||
585 | |||
586 | cleanup: | ||
587 | key->pk_algorithm = MHD_GNUTLS_PK_UNKNOWN; | ||
588 | if (need_free) | ||
589 | MHD__gnutls_free_datum (&_data); | ||
590 | return result; | ||
591 | } | ||
592 | |||
593 | /* Reads the PBKDF2 parameters. | ||
594 | */ | ||
595 | static int | ||
596 | read_pbkdf2_params (ASN1_TYPE pbes2_asn, | ||
597 | const MHD_gnutls_datum_t * der, | ||
598 | struct pbkdf2_params *params) | ||
599 | { | ||
600 | int params_start, params_end; | ||
601 | int params_len, len, result; | ||
602 | ASN1_TYPE pbkdf2_asn = ASN1_TYPE_EMPTY; | ||
603 | char oid[64]; | ||
604 | |||
605 | memset (params, 0, sizeof (params)); | ||
606 | |||
607 | /* Check the key derivation algorithm | ||
608 | */ | ||
609 | len = sizeof (oid); | ||
610 | result = | ||
611 | MHD__asn1_read_value (pbes2_asn, "keyDerivationFunc.algorithm", oid, | ||
612 | &len); | ||
613 | if (result != ASN1_SUCCESS) | ||
614 | { | ||
615 | MHD_gnutls_assert (); | ||
616 | return MHD_gtls_asn2err (result); | ||
617 | } | ||
618 | MHD__gnutls_hard_log ("keyDerivationFunc.algorithm: %s\n", oid); | ||
619 | |||
620 | if (strcmp (oid, PBKDF2_OID) != 0) | ||
621 | { | ||
622 | MHD_gnutls_assert (); | ||
623 | MHD__gnutls_x509_log | ||
624 | ("PKCS #8 key derivation OID '%s' is unsupported.\n", oid); | ||
625 | return MHD_gtls_asn2err (result); | ||
626 | } | ||
627 | |||
628 | result = | ||
629 | MHD__asn1_der_decoding_startEnd (pbes2_asn, der->data, der->size, | ||
630 | "keyDerivationFunc.parameters", | ||
631 | ¶ms_start, ¶ms_end); | ||
632 | if (result != ASN1_SUCCESS) | ||
633 | { | ||
634 | MHD_gnutls_assert (); | ||
635 | return MHD_gtls_asn2err (result); | ||
636 | } | ||
637 | params_len = params_end - params_start + 1; | ||
638 | |||
639 | /* Now check the key derivation and the encryption | ||
640 | * functions. | ||
641 | */ | ||
642 | if ((result = | ||
643 | MHD__asn1_create_element (MHD__gnutls_get_pkix (), | ||
644 | "PKIX1.pkcs-5-PBKDF2-params", | ||
645 | &pbkdf2_asn)) != ASN1_SUCCESS) | ||
646 | { | ||
647 | MHD_gnutls_assert (); | ||
648 | return MHD_gtls_asn2err (result); | ||
649 | } | ||
650 | |||
651 | result = | ||
652 | MHD__asn1_der_decoding (&pbkdf2_asn, &der->data[params_start], | ||
653 | params_len, NULL); | ||
654 | if (result != ASN1_SUCCESS) | ||
655 | { | ||
656 | MHD_gnutls_assert (); | ||
657 | result = MHD_gtls_asn2err (result); | ||
658 | goto error; | ||
659 | } | ||
660 | |||
661 | /* read the salt */ | ||
662 | params->salt_size = sizeof (params->salt); | ||
663 | result = | ||
664 | MHD__asn1_read_value (pbkdf2_asn, "salt.specified", params->salt, | ||
665 | ¶ms->salt_size); | ||
666 | if (result != ASN1_SUCCESS) | ||
667 | { | ||
668 | MHD_gnutls_assert (); | ||
669 | result = MHD_gtls_asn2err (result); | ||
670 | goto error; | ||
671 | } | ||
672 | MHD__gnutls_hard_log ("salt.specified.size: %d\n", params->salt_size); | ||
673 | |||
674 | /* read the iteration count | ||
675 | */ | ||
676 | result = | ||
677 | MHD__gnutls_x509_read_uint (pbkdf2_asn, "iterationCount", | ||
678 | ¶ms->iter_count); | ||
679 | if (result != ASN1_SUCCESS) | ||
680 | { | ||
681 | MHD_gnutls_assert (); | ||
682 | goto error; | ||
683 | } | ||
684 | MHD__gnutls_hard_log ("iterationCount: %d\n", params->iter_count); | ||
685 | |||
686 | /* read the keylength, if it is set. | ||
687 | */ | ||
688 | result = | ||
689 | MHD__gnutls_x509_read_uint (pbkdf2_asn, "keyLength", ¶ms->key_size); | ||
690 | if (result < 0) | ||
691 | { | ||
692 | params->key_size = 0; | ||
693 | } | ||
694 | MHD__gnutls_hard_log ("keyLength: %d\n", params->key_size); | ||
695 | |||
696 | /* We don't read the PRF. We only use the default. | ||
697 | */ | ||
698 | |||
699 | return 0; | ||
700 | |||
701 | error: | ||
702 | MHD__asn1_delete_structure (&pbkdf2_asn); | ||
703 | return result; | ||
704 | |||
705 | } | ||
706 | |||
707 | /* Reads the PBE parameters from PKCS-12 schemas (*&#%*&#% RSA). | ||
708 | */ | ||
709 | static int | ||
710 | readMHD_pkcs12_kdf_params (ASN1_TYPE pbes2_asn, struct pbkdf2_params *params) | ||
711 | { | ||
712 | int result; | ||
713 | |||
714 | memset (params, 0, sizeof (params)); | ||
715 | |||
716 | /* read the salt */ | ||
717 | params->salt_size = sizeof (params->salt); | ||
718 | result = | ||
719 | MHD__asn1_read_value (pbes2_asn, "salt", params->salt, | ||
720 | ¶ms->salt_size); | ||
721 | if (result != ASN1_SUCCESS) | ||
722 | { | ||
723 | MHD_gnutls_assert (); | ||
724 | result = MHD_gtls_asn2err (result); | ||
725 | goto error; | ||
726 | } | ||
727 | MHD__gnutls_hard_log ("salt.size: %d\n", params->salt_size); | ||
728 | |||
729 | /* read the iteration count | ||
730 | */ | ||
731 | result = | ||
732 | MHD__gnutls_x509_read_uint (pbes2_asn, "iterations", ¶ms->iter_count); | ||
733 | if (result != ASN1_SUCCESS) | ||
734 | { | ||
735 | MHD_gnutls_assert (); | ||
736 | goto error; | ||
737 | } | ||
738 | MHD__gnutls_hard_log ("iterationCount: %d\n", params->iter_count); | ||
739 | |||
740 | params->key_size = 0; | ||
741 | |||
742 | return 0; | ||
743 | |||
744 | error: | ||
745 | return result; | ||
746 | |||
747 | } | ||
748 | |||
749 | /* Converts an OID to a gnutls cipher type. | ||
750 | */ | ||
751 | static int | ||
752 | oid2cipher (const char *oid, enum MHD_GNUTLS_CipherAlgorithm *algo) | ||
753 | { | ||
754 | |||
755 | *algo = 0; | ||
756 | |||
757 | if (strcmp (oid, DES_EDE3_CBC_OID) == 0) | ||
758 | { | ||
759 | *algo = MHD_GNUTLS_CIPHER_3DES_CBC; | ||
760 | return 0; | ||
761 | } | ||
762 | |||
763 | if (strcmp (oid, DES_CBC_OID) == 0) | ||
764 | { | ||
765 | *algo = MHD_GNUTLS_CIPHER_DES_CBC; | ||
766 | return 0; | ||
767 | } | ||
768 | |||
769 | MHD__gnutls_x509_log ("PKCS #8 encryption OID '%s' is unsupported.\n", oid); | ||
770 | return GNUTLS_E_UNKNOWN_CIPHER_TYPE; | ||
771 | } | ||
772 | |||
773 | static int | ||
774 | read_pbe_enc_params (ASN1_TYPE pbes2_asn, | ||
775 | const MHD_gnutls_datum_t * der, | ||
776 | struct pbe_enc_params *params) | ||
777 | { | ||
778 | int params_start, params_end; | ||
779 | int params_len, len, result; | ||
780 | ASN1_TYPE pbe_asn = ASN1_TYPE_EMPTY; | ||
781 | char oid[64]; | ||
782 | |||
783 | memset (params, 0, sizeof (params)); | ||
784 | |||
785 | /* Check the encryption algorithm | ||
786 | */ | ||
787 | len = sizeof (oid); | ||
788 | result = | ||
789 | MHD__asn1_read_value (pbes2_asn, "encryptionScheme.algorithm", oid, &len); | ||
790 | if (result != ASN1_SUCCESS) | ||
791 | { | ||
792 | MHD_gnutls_assert (); | ||
793 | goto error; | ||
794 | } | ||
795 | MHD__gnutls_hard_log ("encryptionScheme.algorithm: %s\n", oid); | ||
796 | |||
797 | if ((result = oid2cipher (oid, ¶ms->cipher)) < 0) | ||
798 | { | ||
799 | MHD_gnutls_assert (); | ||
800 | goto error; | ||
801 | } | ||
802 | |||
803 | result = | ||
804 | MHD__asn1_der_decoding_startEnd (pbes2_asn, der->data, der->size, | ||
805 | "encryptionScheme.parameters", | ||
806 | ¶ms_start, ¶ms_end); | ||
807 | if (result != ASN1_SUCCESS) | ||
808 | { | ||
809 | MHD_gnutls_assert (); | ||
810 | return MHD_gtls_asn2err (result); | ||
811 | } | ||
812 | params_len = params_end - params_start + 1; | ||
813 | |||
814 | /* Now check the encryption parameters. | ||
815 | */ | ||
816 | if ((result = | ||
817 | MHD__asn1_create_element (MHD__gnutls_get_pkix (), | ||
818 | "PKIX1.pkcs-5-des-EDE3-CBC-params", | ||
819 | &pbe_asn)) != ASN1_SUCCESS) | ||
820 | { | ||
821 | MHD_gnutls_assert (); | ||
822 | return MHD_gtls_asn2err (result); | ||
823 | } | ||
824 | |||
825 | result = | ||
826 | MHD__asn1_der_decoding (&pbe_asn, &der->data[params_start], params_len, | ||
827 | NULL); | ||
828 | if (result != ASN1_SUCCESS) | ||
829 | { | ||
830 | MHD_gnutls_assert (); | ||
831 | result = MHD_gtls_asn2err (result); | ||
832 | goto error; | ||
833 | } | ||
834 | |||
835 | /* read the IV */ | ||
836 | params->iv_size = sizeof (params->iv); | ||
837 | result = MHD__asn1_read_value (pbe_asn, "", params->iv, ¶ms->iv_size); | ||
838 | if (result != ASN1_SUCCESS) | ||
839 | { | ||
840 | MHD_gnutls_assert (); | ||
841 | result = MHD_gtls_asn2err (result); | ||
842 | goto error; | ||
843 | } | ||
844 | MHD__gnutls_hard_log ("IV.size: %d\n", params->iv_size); | ||
845 | |||
846 | return 0; | ||
847 | |||
848 | error: | ||
849 | MHD__asn1_delete_structure (&pbe_asn); | ||
850 | return result; | ||
851 | |||
852 | } | ||
853 | |||
854 | static int | ||
855 | decrypt_data (schema_id schema, ASN1_TYPE pkcs8_asn, | ||
856 | const char *root, const char *password, | ||
857 | const struct pbkdf2_params *kdf_params, | ||
858 | const struct pbe_enc_params *enc_params, | ||
859 | MHD_gnutls_datum_t * decrypted_data) | ||
860 | { | ||
861 | int result; | ||
862 | int data_size; | ||
863 | opaque *data = NULL, *key = NULL; | ||
864 | MHD_gnutls_datum_t dkey, d_iv; | ||
865 | cipher_hd_t ch = NULL; | ||
866 | int key_size; | ||
867 | |||
868 | data_size = 0; | ||
869 | result = MHD__asn1_read_value (pkcs8_asn, root, NULL, &data_size); | ||
870 | if (result != ASN1_MEM_ERROR) | ||
871 | { | ||
872 | MHD_gnutls_assert (); | ||
873 | return MHD_gtls_asn2err (result); | ||
874 | } | ||
875 | |||
876 | data = MHD_gnutls_malloc (data_size); | ||
877 | if (data == NULL) | ||
878 | { | ||
879 | MHD_gnutls_assert (); | ||
880 | return GNUTLS_E_MEMORY_ERROR; | ||
881 | } | ||
882 | |||
883 | result = MHD__asn1_read_value (pkcs8_asn, root, data, &data_size); | ||
884 | if (result != ASN1_SUCCESS) | ||
885 | { | ||
886 | MHD_gnutls_assert (); | ||
887 | result = MHD_gtls_asn2err (result); | ||
888 | goto error; | ||
889 | } | ||
890 | |||
891 | if (kdf_params->key_size == 0) | ||
892 | { | ||
893 | key_size = MHD__gnutls_cipher_get_key_size (enc_params->cipher); | ||
894 | } | ||
895 | else | ||
896 | key_size = kdf_params->key_size; | ||
897 | |||
898 | key = MHD_gnutls_alloca (key_size); | ||
899 | if (key == NULL) | ||
900 | { | ||
901 | MHD_gnutls_assert (); | ||
902 | result = GNUTLS_E_MEMORY_ERROR; | ||
903 | goto error; | ||
904 | } | ||
905 | |||
906 | /* generate the key | ||
907 | */ | ||
908 | if (schema == PBES2) | ||
909 | { | ||
910 | result = MHD_gc_pbkdf2_sha1 (password, strlen (password), | ||
911 | (const char *) kdf_params->salt, | ||
912 | kdf_params->salt_size, | ||
913 | kdf_params->iter_count, (char *) key, | ||
914 | key_size); | ||
915 | |||
916 | if (result != GC_OK) | ||
917 | { | ||
918 | MHD_gnutls_assert (); | ||
919 | result = GNUTLS_E_DECRYPTION_FAILED; | ||
920 | goto error; | ||
921 | } | ||
922 | } | ||
923 | else | ||
924 | { | ||
925 | result = | ||
926 | MHD_pkcs12_string_to_key (1 /*KEY*/, kdf_params->salt, | ||
927 | kdf_params->salt_size, | ||
928 | kdf_params->iter_count, password, | ||
929 | key_size, key); | ||
930 | |||
931 | if (result < 0) | ||
932 | { | ||
933 | MHD_gnutls_assert (); | ||
934 | goto error; | ||
935 | } | ||
936 | } | ||
937 | |||
938 | /* do the decryption. | ||
939 | */ | ||
940 | dkey.data = key; | ||
941 | dkey.size = key_size; | ||
942 | |||
943 | d_iv.data = (opaque *) enc_params->iv; | ||
944 | d_iv.size = enc_params->iv_size; | ||
945 | ch = MHD_gtls_cipher_init (enc_params->cipher, &dkey, &d_iv); | ||
946 | |||
947 | MHD_gnutls_afree (key); | ||
948 | key = NULL; | ||
949 | |||
950 | if (ch == NULL) | ||
951 | { | ||
952 | MHD_gnutls_assert (); | ||
953 | result = GNUTLS_E_DECRYPTION_FAILED; | ||
954 | goto error; | ||
955 | } | ||
956 | |||
957 | result = MHD_gtls_cipher_decrypt (ch, data, data_size); | ||
958 | if (result < 0) | ||
959 | { | ||
960 | MHD_gnutls_assert (); | ||
961 | goto error; | ||
962 | } | ||
963 | |||
964 | decrypted_data->data = data; | ||
965 | |||
966 | if (MHD_gtls_cipher_get_block_size (enc_params->cipher) != 1) | ||
967 | decrypted_data->size = data_size - data[data_size - 1]; | ||
968 | else | ||
969 | decrypted_data->size = data_size; | ||
970 | |||
971 | MHD_gnutls_cipher_deinit (ch); | ||
972 | |||
973 | return 0; | ||
974 | |||
975 | error: | ||
976 | MHD_gnutls_free (data); | ||
977 | MHD_gnutls_afree (key); | ||
978 | if (ch != NULL) | ||
979 | MHD_gnutls_cipher_deinit (ch); | ||
980 | return result; | ||
981 | } | ||
982 | |||
983 | |||
984 | #endif | ||