diff options
Diffstat (limited to 'src/daemon/https/x509/privkey_pkcs8.c')
-rw-r--r-- | src/daemon/https/x509/privkey_pkcs8.c | 2219 |
1 files changed, 2219 insertions, 0 deletions
diff --git a/src/daemon/https/x509/privkey_pkcs8.c b/src/daemon/https/x509/privkey_pkcs8.c new file mode 100644 index 00000000..2f1921bb --- /dev/null +++ b/src/daemon/https/x509/privkey_pkcs8.c | |||
@@ -0,0 +1,2219 @@ | |||
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 <dn.h> | ||
38 | #include <pkcs12.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 | gnutls_cipher_algorithm_t cipher; | ||
67 | opaque iv[8]; | ||
68 | int iv_size; | ||
69 | }; | ||
70 | |||
71 | static int generate_key (schema_id schema, const char *password, | ||
72 | struct pbkdf2_params *kdf_params, | ||
73 | struct pbe_enc_params *enc_params, | ||
74 | gnutls_datum_t * key); | ||
75 | static int read_pbkdf2_params (ASN1_TYPE pbes2_asn, | ||
76 | const gnutls_datum_t * der, | ||
77 | struct pbkdf2_params *params); | ||
78 | static int read_pbe_enc_params (ASN1_TYPE pbes2_asn, | ||
79 | const gnutls_datum_t * der, | ||
80 | struct pbe_enc_params *params); | ||
81 | static int decrypt_data (schema_id, ASN1_TYPE pkcs8_asn, const char *root, | ||
82 | const char *password, | ||
83 | const struct pbkdf2_params *kdf_params, | ||
84 | const struct pbe_enc_params *enc_params, | ||
85 | gnutls_datum_t * decrypted_data); | ||
86 | static int decode_private_key_info (const gnutls_datum_t * der, | ||
87 | gnutls_x509_privkey_t pkey); | ||
88 | static int write_schema_params (schema_id schema, ASN1_TYPE pkcs8_asn, | ||
89 | const char *where, | ||
90 | const struct pbkdf2_params *kdf_params, | ||
91 | const struct pbe_enc_params *enc_params); | ||
92 | static int encrypt_data (const gnutls_datum_t * plain, | ||
93 | const struct pbe_enc_params *enc_params, | ||
94 | gnutls_datum_t * key, gnutls_datum_t * encrypted); | ||
95 | |||
96 | static int read_pkcs12_kdf_params (ASN1_TYPE pbes2_asn, | ||
97 | struct pbkdf2_params *params); | ||
98 | static int write_pkcs12_kdf_params (ASN1_TYPE pbes2_asn, | ||
99 | const struct pbkdf2_params *params); | ||
100 | |||
101 | #define PEM_PKCS8 "ENCRYPTED PRIVATE KEY" | ||
102 | #define PEM_UNENCRYPTED_PKCS8 "PRIVATE KEY" | ||
103 | |||
104 | /* Returns a negative error code if the encryption schema in | ||
105 | * the OID is not supported. The schema ID is returned. | ||
106 | */ | ||
107 | inline static int | ||
108 | check_schema (const char *oid) | ||
109 | { | ||
110 | |||
111 | if (strcmp (oid, PBES2_OID) == 0) | ||
112 | return PBES2; | ||
113 | |||
114 | if (strcmp (oid, PKCS12_PBE_3DES_SHA1_OID) == 0) | ||
115 | return PKCS12_3DES_SHA1; | ||
116 | |||
117 | if (strcmp (oid, PKCS12_PBE_ARCFOUR_SHA1_OID) == 0) | ||
118 | return PKCS12_ARCFOUR_SHA1; | ||
119 | |||
120 | if (strcmp (oid, PKCS12_PBE_RC2_40_SHA1_OID) == 0) | ||
121 | return PKCS12_RC2_40_SHA1; | ||
122 | |||
123 | _gnutls_x509_log ("PKCS encryption schema OID '%s' is unsupported.\n", oid); | ||
124 | |||
125 | return GNUTLS_E_UNKNOWN_CIPHER_TYPE; | ||
126 | } | ||
127 | |||
128 | /* Encodes a private key to the raw format PKCS #8 needs. | ||
129 | * For RSA it is a PKCS #1 DER private key and for DSA it is | ||
130 | * an ASN.1 INTEGER of the x value. | ||
131 | */ | ||
132 | inline static int | ||
133 | _encode_privkey (gnutls_x509_privkey pkey, gnutls_datum * raw) | ||
134 | { | ||
135 | size_t size = 0; | ||
136 | opaque *data = NULL; | ||
137 | int ret; | ||
138 | ASN1_TYPE spk = ASN1_TYPE_EMPTY; | ||
139 | |||
140 | switch (pkey->pk_algorithm) | ||
141 | { | ||
142 | case GNUTLS_PK_RSA: | ||
143 | ret = | ||
144 | gnutls_x509_privkey_export (pkey, GNUTLS_X509_FMT_DER, NULL, &size); | ||
145 | if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) | ||
146 | { | ||
147 | gnutls_assert (); | ||
148 | goto error; | ||
149 | } | ||
150 | |||
151 | data = gnutls_malloc (size); | ||
152 | if (data == NULL) | ||
153 | { | ||
154 | gnutls_assert (); | ||
155 | ret = GNUTLS_E_MEMORY_ERROR; | ||
156 | goto error; | ||
157 | } | ||
158 | |||
159 | ret = | ||
160 | gnutls_x509_privkey_export (pkey, GNUTLS_X509_FMT_DER, data, &size); | ||
161 | if (ret < 0) | ||
162 | { | ||
163 | gnutls_assert (); | ||
164 | goto error; | ||
165 | } | ||
166 | |||
167 | raw->data = data; | ||
168 | raw->size = size; | ||
169 | break; | ||
170 | default: | ||
171 | gnutls_assert (); | ||
172 | return GNUTLS_E_INVALID_REQUEST; | ||
173 | } | ||
174 | |||
175 | return 0; | ||
176 | |||
177 | error: | ||
178 | gnutls_free (data); | ||
179 | asn1_delete_structure (&spk); | ||
180 | return ret; | ||
181 | |||
182 | } | ||
183 | |||
184 | /* | ||
185 | * Encodes a PKCS #1 private key to a PKCS #8 private key | ||
186 | * info. The output will be allocated and stored into der. Also | ||
187 | * the ASN1_TYPE of private key info will be returned. | ||
188 | */ | ||
189 | static int | ||
190 | encode_to_private_key_info (gnutls_x509_privkey_t pkey, | ||
191 | gnutls_datum_t * der, ASN1_TYPE * pkey_info) | ||
192 | { | ||
193 | int result, len; | ||
194 | opaque null = 0; | ||
195 | const char *oid; | ||
196 | gnutls_datum algo_params = | ||
197 | { NULL, 0}; | ||
198 | gnutls_datum algo_privkey = | ||
199 | { NULL, 0}; | ||
200 | |||
201 | if (pkey->pk_algorithm == GNUTLS_PK_RSA) | ||
202 | { | ||
203 | oid = PK_PKIX1_RSA_OID; | ||
204 | /* parameters are null | ||
205 | */ | ||
206 | } | ||
207 | else | ||
208 | { | ||
209 | oid = PK_DSA_OID; | ||
210 | result = | ||
211 | _gnutls_x509_write_dsa_params (pkey->params, pkey->params_size, | ||
212 | &algo_params); | ||
213 | if (result < 0) | ||
214 | { | ||
215 | gnutls_assert (); | ||
216 | return result; | ||
217 | } | ||
218 | } | ||
219 | |||
220 | if ((result = | ||
221 | asn1_create_element (_gnutls_get_pkix (), | ||
222 | "PKIX1.pkcs-8-PrivateKeyInfo", | ||
223 | pkey_info)) != ASN1_SUCCESS) | ||
224 | { | ||
225 | gnutls_assert (); | ||
226 | result = _gnutls_asn2err (result); | ||
227 | goto error; | ||
228 | } | ||
229 | |||
230 | /* Write the version. | ||
231 | */ | ||
232 | result = asn1_write_value (*pkey_info, "version", &null, 1); | ||
233 | if (result != ASN1_SUCCESS) | ||
234 | { | ||
235 | gnutls_assert (); | ||
236 | result = _gnutls_asn2err (result); | ||
237 | goto error; | ||
238 | } | ||
239 | |||
240 | /* write the privateKeyAlgorithm | ||
241 | * fields. (OID+NULL data) | ||
242 | */ | ||
243 | result = | ||
244 | asn1_write_value (*pkey_info, "privateKeyAlgorithm.algorithm", oid, 1); | ||
245 | if (result != ASN1_SUCCESS) | ||
246 | { | ||
247 | gnutls_assert (); | ||
248 | result = _gnutls_asn2err (result); | ||
249 | goto error; | ||
250 | } | ||
251 | |||
252 | result = | ||
253 | asn1_write_value (*pkey_info, "privateKeyAlgorithm.parameters", | ||
254 | algo_params.data, algo_params.size); | ||
255 | _gnutls_free_datum (&algo_params); | ||
256 | if (result != ASN1_SUCCESS) | ||
257 | { | ||
258 | gnutls_assert (); | ||
259 | result = _gnutls_asn2err (result); | ||
260 | goto error; | ||
261 | } | ||
262 | |||
263 | /* Write the raw private key | ||
264 | */ | ||
265 | result = _encode_privkey (pkey, &algo_privkey); | ||
266 | if (result < 0) | ||
267 | { | ||
268 | gnutls_assert (); | ||
269 | goto error; | ||
270 | } | ||
271 | |||
272 | result = | ||
273 | asn1_write_value (*pkey_info, "privateKey", algo_privkey.data, | ||
274 | algo_privkey.size); | ||
275 | _gnutls_free_datum (&algo_privkey); | ||
276 | |||
277 | if (result != ASN1_SUCCESS) | ||
278 | { | ||
279 | gnutls_assert (); | ||
280 | result = _gnutls_asn2err (result); | ||
281 | goto error; | ||
282 | } | ||
283 | |||
284 | /* Append an empty Attributes field. | ||
285 | */ | ||
286 | result = asn1_write_value (*pkey_info, "attributes", NULL, 0); | ||
287 | if (result != ASN1_SUCCESS) | ||
288 | { | ||
289 | gnutls_assert (); | ||
290 | result = _gnutls_asn2err (result); | ||
291 | goto error; | ||
292 | } | ||
293 | |||
294 | /* DER Encode the generated private key info. | ||
295 | */ | ||
296 | len = 0; | ||
297 | result = asn1_der_coding (*pkey_info, "", NULL, &len, NULL); | ||
298 | if (result != ASN1_MEM_ERROR) | ||
299 | { | ||
300 | gnutls_assert (); | ||
301 | result = _gnutls_asn2err (result); | ||
302 | goto error; | ||
303 | } | ||
304 | |||
305 | /* allocate data for the der | ||
306 | */ | ||
307 | der->size = len; | ||
308 | der->data = gnutls_malloc (len); | ||
309 | if (der->data == NULL) | ||
310 | { | ||
311 | gnutls_assert (); | ||
312 | return GNUTLS_E_MEMORY_ERROR; | ||
313 | } | ||
314 | |||
315 | result = asn1_der_coding (*pkey_info, "", der->data, &len, NULL); | ||
316 | if (result != ASN1_SUCCESS) | ||
317 | { | ||
318 | gnutls_assert (); | ||
319 | result = _gnutls_asn2err (result); | ||
320 | goto error; | ||
321 | } | ||
322 | |||
323 | return 0; | ||
324 | |||
325 | error: | ||
326 | asn1_delete_structure (pkey_info); | ||
327 | _gnutls_free_datum (&algo_params); | ||
328 | _gnutls_free_datum (&algo_privkey); | ||
329 | return result; | ||
330 | |||
331 | } | ||
332 | |||
333 | /* Converts a PKCS #8 private key info to | ||
334 | * a PKCS #8 EncryptedPrivateKeyInfo. | ||
335 | */ | ||
336 | static int | ||
337 | encode_to_pkcs8_key (schema_id schema, const gnutls_datum_t * der_key, | ||
338 | const char *password, ASN1_TYPE * out) | ||
339 | { | ||
340 | int result; | ||
341 | gnutls_datum_t key = | ||
342 | { NULL, 0}; | ||
343 | gnutls_datum_t tmp = | ||
344 | { NULL, 0}; | ||
345 | ASN1_TYPE pkcs8_asn = ASN1_TYPE_EMPTY; | ||
346 | struct pbkdf2_params kdf_params; | ||
347 | struct pbe_enc_params enc_params; | ||
348 | |||
349 | if ((result = | ||
350 | asn1_create_element (_gnutls_get_pkix (), | ||
351 | "PKIX1.pkcs-8-EncryptedPrivateKeyInfo", | ||
352 | &pkcs8_asn)) != ASN1_SUCCESS) | ||
353 | { | ||
354 | gnutls_assert (); | ||
355 | result = _gnutls_asn2err (result); | ||
356 | goto error; | ||
357 | } | ||
358 | |||
359 | /* Write the encryption schema OID | ||
360 | */ | ||
361 | switch (schema) | ||
362 | { | ||
363 | case PBES2: | ||
364 | result = | ||
365 | asn1_write_value (pkcs8_asn, "encryptionAlgorithm.algorithm", | ||
366 | PBES2_OID, 1); | ||
367 | break; | ||
368 | case PKCS12_3DES_SHA1: | ||
369 | result = | ||
370 | asn1_write_value (pkcs8_asn, "encryptionAlgorithm.algorithm", | ||
371 | PKCS12_PBE_3DES_SHA1_OID, 1); | ||
372 | break; | ||
373 | case PKCS12_ARCFOUR_SHA1: | ||
374 | result = | ||
375 | asn1_write_value (pkcs8_asn, "encryptionAlgorithm.algorithm", | ||
376 | PKCS12_PBE_ARCFOUR_SHA1_OID, 1); | ||
377 | break; | ||
378 | case PKCS12_RC2_40_SHA1: | ||
379 | result = | ||
380 | asn1_write_value (pkcs8_asn, "encryptionAlgorithm.algorithm", | ||
381 | PKCS12_PBE_RC2_40_SHA1_OID, 1); | ||
382 | break; | ||
383 | |||
384 | } | ||
385 | |||
386 | if (result != ASN1_SUCCESS) | ||
387 | { | ||
388 | gnutls_assert (); | ||
389 | result = _gnutls_asn2err (result); | ||
390 | goto error; | ||
391 | } | ||
392 | |||
393 | /* Generate a symmetric key. | ||
394 | */ | ||
395 | |||
396 | result = generate_key (schema, password, &kdf_params, &enc_params, &key); | ||
397 | if (result < 0) | ||
398 | { | ||
399 | gnutls_assert (); | ||
400 | goto error; | ||
401 | } | ||
402 | |||
403 | result = | ||
404 | write_schema_params (schema, pkcs8_asn, | ||
405 | "encryptionAlgorithm.parameters", &kdf_params, | ||
406 | &enc_params); | ||
407 | if (result < 0) | ||
408 | { | ||
409 | gnutls_assert (); | ||
410 | goto error; | ||
411 | } | ||
412 | |||
413 | /* Parameters have been encoded. Now | ||
414 | * encrypt the Data. | ||
415 | */ | ||
416 | result = encrypt_data (der_key, &enc_params, &key, &tmp); | ||
417 | if (result < 0) | ||
418 | { | ||
419 | gnutls_assert (); | ||
420 | goto error; | ||
421 | } | ||
422 | |||
423 | /* write the encrypted data. | ||
424 | */ | ||
425 | result = asn1_write_value (pkcs8_asn, "encryptedData", tmp.data, tmp.size); | ||
426 | if (result != ASN1_SUCCESS) | ||
427 | { | ||
428 | gnutls_assert (); | ||
429 | result = _gnutls_asn2err (result); | ||
430 | goto error; | ||
431 | } | ||
432 | |||
433 | _gnutls_free_datum (&tmp); | ||
434 | _gnutls_free_datum (&key); | ||
435 | |||
436 | *out = pkcs8_asn; | ||
437 | |||
438 | return 0; | ||
439 | |||
440 | error: | ||
441 | _gnutls_free_datum (&key); | ||
442 | _gnutls_free_datum (&tmp); | ||
443 | asn1_delete_structure (&pkcs8_asn); | ||
444 | return result; | ||
445 | } | ||
446 | |||
447 | /** | ||
448 | * gnutls_x509_privkey_export_pkcs8 - This function will export the private key to PKCS8 format | ||
449 | * @key: Holds the key | ||
450 | * @format: the format of output params. One of PEM or DER. | ||
451 | * @password: the password that will be used to encrypt the key. | ||
452 | * @flags: an ORed sequence of gnutls_pkcs_encrypt_flags_t | ||
453 | * @output_data: will contain a private key PEM or DER encoded | ||
454 | * @output_data_size: holds the size of output_data (and will be | ||
455 | * replaced by the actual size of parameters) | ||
456 | * | ||
457 | * This function will export the private key to a PKCS8 structure. | ||
458 | * Both RSA and DSA keys can be exported. For DSA keys we use | ||
459 | * PKCS #11 definitions. If the flags do not specify the encryption | ||
460 | * cipher, then the default 3DES (PBES2) will be used. | ||
461 | * | ||
462 | * The @password can be either ASCII or UTF-8 in the default PBES2 | ||
463 | * encryption schemas, or ASCII for the PKCS12 schemas. | ||
464 | * | ||
465 | * If the buffer provided is not long enough to hold the output, then | ||
466 | * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will | ||
467 | * be returned. | ||
468 | * | ||
469 | * If the structure is PEM encoded, it will have a header | ||
470 | * of "BEGIN ENCRYPTED PRIVATE KEY" or "BEGIN PRIVATE KEY" if | ||
471 | * encryption is not used. | ||
472 | * | ||
473 | * Return value: In case of failure a negative value will be | ||
474 | * returned, and 0 on success. | ||
475 | * | ||
476 | **/ | ||
477 | int | ||
478 | gnutls_x509_privkey_export_pkcs8 (gnutls_x509_privkey_t key, | ||
479 | gnutls_x509_crt_fmt_t format, | ||
480 | const char *password, | ||
481 | unsigned int flags, | ||
482 | void *output_data, | ||
483 | size_t * output_data_size) | ||
484 | { | ||
485 | ASN1_TYPE pkcs8_asn, pkey_info; | ||
486 | int ret; | ||
487 | gnutls_datum_t tmp; | ||
488 | schema_id schema; | ||
489 | |||
490 | if (key == NULL) | ||
491 | { | ||
492 | gnutls_assert (); | ||
493 | return GNUTLS_E_INVALID_REQUEST; | ||
494 | } | ||
495 | |||
496 | /* Get the private key info | ||
497 | * tmp holds the DER encoding. | ||
498 | */ | ||
499 | ret = encode_to_private_key_info (key, &tmp, &pkey_info); | ||
500 | if (ret < 0) | ||
501 | { | ||
502 | gnutls_assert (); | ||
503 | return ret; | ||
504 | } | ||
505 | |||
506 | if (flags & GNUTLS_PKCS_USE_PKCS12_3DES) | ||
507 | schema = PKCS12_3DES_SHA1; | ||
508 | else if (flags & GNUTLS_PKCS_USE_PKCS12_ARCFOUR) | ||
509 | schema = PKCS12_ARCFOUR_SHA1; | ||
510 | else if (flags & GNUTLS_PKCS_USE_PKCS12_RC2_40) | ||
511 | schema = PKCS12_RC2_40_SHA1; | ||
512 | else | ||
513 | schema = PBES2; | ||
514 | |||
515 | if ((flags & GNUTLS_PKCS_PLAIN) || password == NULL) | ||
516 | { | ||
517 | _gnutls_free_datum (&tmp); | ||
518 | |||
519 | ret = | ||
520 | _gnutls_x509_export_int (pkey_info, format, | ||
521 | PEM_UNENCRYPTED_PKCS8, | ||
522 | output_data, output_data_size); | ||
523 | |||
524 | asn1_delete_structure (&pkey_info); | ||
525 | } | ||
526 | else | ||
527 | { | ||
528 | asn1_delete_structure (&pkey_info); /* we don't need it */ | ||
529 | |||
530 | ret = encode_to_pkcs8_key (schema, &tmp, password, &pkcs8_asn); | ||
531 | _gnutls_free_datum (&tmp); | ||
532 | |||
533 | if (ret < 0) | ||
534 | { | ||
535 | gnutls_assert (); | ||
536 | return ret; | ||
537 | } | ||
538 | |||
539 | ret = | ||
540 | _gnutls_x509_export_int (pkcs8_asn, format, PEM_PKCS8, | ||
541 | output_data, output_data_size); | ||
542 | |||
543 | asn1_delete_structure (&pkcs8_asn); | ||
544 | } | ||
545 | |||
546 | return ret; | ||
547 | } | ||
548 | |||
549 | /* Read the parameters cipher, IV, salt etc using the given | ||
550 | * schema ID. | ||
551 | */ | ||
552 | static int | ||
553 | read_pkcs_schema_params (schema_id schema, const char *password, | ||
554 | const opaque * data, int data_size, | ||
555 | struct pbkdf2_params *kdf_params, | ||
556 | struct pbe_enc_params *enc_params) | ||
557 | { | ||
558 | ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY; | ||
559 | int result; | ||
560 | gnutls_datum_t tmp; | ||
561 | |||
562 | switch (schema) | ||
563 | { | ||
564 | |||
565 | case PBES2: | ||
566 | |||
567 | /* Now check the key derivation and the encryption | ||
568 | * functions. | ||
569 | */ | ||
570 | if ((result = | ||
571 | asn1_create_element (_gnutls_get_pkix (), | ||
572 | "PKIX1.pkcs-5-PBES2-params", | ||
573 | &pbes2_asn)) != ASN1_SUCCESS) | ||
574 | { | ||
575 | gnutls_assert (); | ||
576 | result = _gnutls_asn2err (result); | ||
577 | goto error; | ||
578 | } | ||
579 | |||
580 | /* Decode the parameters. | ||
581 | */ | ||
582 | result = asn1_der_decoding (&pbes2_asn, data, data_size, NULL); | ||
583 | if (result != ASN1_SUCCESS) | ||
584 | { | ||
585 | gnutls_assert (); | ||
586 | result = _gnutls_asn2err (result); | ||
587 | goto error; | ||
588 | } | ||
589 | |||
590 | tmp.data = (opaque *) data; | ||
591 | tmp.size = data_size; | ||
592 | |||
593 | result = read_pbkdf2_params (pbes2_asn, &tmp, kdf_params); | ||
594 | if (result < 0) | ||
595 | { | ||
596 | gnutls_assert (); | ||
597 | result = _gnutls_asn2err (result); | ||
598 | goto error; | ||
599 | } | ||
600 | |||
601 | result = read_pbe_enc_params (pbes2_asn, &tmp, enc_params); | ||
602 | if (result < 0) | ||
603 | { | ||
604 | gnutls_assert (); | ||
605 | result = _gnutls_asn2err (result); | ||
606 | goto error; | ||
607 | } | ||
608 | |||
609 | asn1_delete_structure (&pbes2_asn); | ||
610 | return 0; | ||
611 | break; | ||
612 | |||
613 | case PKCS12_3DES_SHA1: | ||
614 | case PKCS12_ARCFOUR_SHA1: | ||
615 | case PKCS12_RC2_40_SHA1: | ||
616 | |||
617 | if ((schema) == PKCS12_3DES_SHA1) | ||
618 | { | ||
619 | enc_params->cipher = GNUTLS_CIPHER_3DES_CBC; | ||
620 | enc_params->iv_size = 8; | ||
621 | } | ||
622 | else if ((schema) == PKCS12_ARCFOUR_SHA1) | ||
623 | { | ||
624 | enc_params->cipher = GNUTLS_CIPHER_ARCFOUR_128; | ||
625 | enc_params->iv_size = 0; | ||
626 | } | ||
627 | else if ((schema) == PKCS12_RC2_40_SHA1) | ||
628 | { | ||
629 | enc_params->cipher = GNUTLS_CIPHER_RC2_40_CBC; | ||
630 | enc_params->iv_size = 8; | ||
631 | } | ||
632 | |||
633 | if ((result = | ||
634 | asn1_create_element (_gnutls_get_pkix (), | ||
635 | "PKIX1.pkcs-12-PbeParams", | ||
636 | &pbes2_asn)) != ASN1_SUCCESS) | ||
637 | { | ||
638 | gnutls_assert (); | ||
639 | result = _gnutls_asn2err (result); | ||
640 | goto error; | ||
641 | } | ||
642 | |||
643 | /* Decode the parameters. | ||
644 | */ | ||
645 | result = asn1_der_decoding (&pbes2_asn, data, data_size, NULL); | ||
646 | if (result != ASN1_SUCCESS) | ||
647 | { | ||
648 | gnutls_assert (); | ||
649 | result = _gnutls_asn2err (result); | ||
650 | goto error; | ||
651 | } | ||
652 | |||
653 | result = read_pkcs12_kdf_params (pbes2_asn, kdf_params); | ||
654 | if (result < 0) | ||
655 | { | ||
656 | gnutls_assert (); | ||
657 | goto error; | ||
658 | } | ||
659 | |||
660 | if (enc_params->iv_size) | ||
661 | { | ||
662 | result = | ||
663 | _pkcs12_string_to_key (2 /*IV*/, kdf_params->salt, | ||
664 | kdf_params->salt_size, | ||
665 | kdf_params->iter_count, password, | ||
666 | enc_params->iv_size, enc_params->iv); | ||
667 | if (result < 0) | ||
668 | { | ||
669 | gnutls_assert (); | ||
670 | goto error; | ||
671 | } | ||
672 | |||
673 | } | ||
674 | |||
675 | asn1_delete_structure (&pbes2_asn); | ||
676 | |||
677 | return 0; | ||
678 | break; | ||
679 | |||
680 | } /* switch */ | ||
681 | |||
682 | return GNUTLS_E_UNKNOWN_CIPHER_TYPE; | ||
683 | |||
684 | error: | ||
685 | asn1_delete_structure (&pbes2_asn); | ||
686 | return result; | ||
687 | } | ||
688 | |||
689 | /* Converts a PKCS #8 key to | ||
690 | * an internal structure (gnutls_private_key) | ||
691 | * (normally a PKCS #1 encoded RSA key) | ||
692 | */ | ||
693 | static int | ||
694 | decode_pkcs8_key (const gnutls_datum_t * raw_key, | ||
695 | const char *password, gnutls_x509_privkey_t pkey) | ||
696 | { | ||
697 | int result, len; | ||
698 | char enc_oid[64]; | ||
699 | gnutls_datum_t tmp; | ||
700 | ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY, pkcs8_asn = ASN1_TYPE_EMPTY; | ||
701 | int params_start, params_end, params_len; | ||
702 | struct pbkdf2_params kdf_params; | ||
703 | struct pbe_enc_params enc_params; | ||
704 | schema_id schema; | ||
705 | |||
706 | if ((result = | ||
707 | asn1_create_element (_gnutls_get_pkix (), | ||
708 | "PKIX1.pkcs-8-EncryptedPrivateKeyInfo", | ||
709 | &pkcs8_asn)) != ASN1_SUCCESS) | ||
710 | { | ||
711 | gnutls_assert (); | ||
712 | result = _gnutls_asn2err (result); | ||
713 | goto error; | ||
714 | } | ||
715 | |||
716 | result = asn1_der_decoding (&pkcs8_asn, raw_key->data, raw_key->size, NULL); | ||
717 | if (result != ASN1_SUCCESS) | ||
718 | { | ||
719 | gnutls_assert (); | ||
720 | result = _gnutls_asn2err (result); | ||
721 | goto error; | ||
722 | } | ||
723 | |||
724 | /* Check the encryption schema OID | ||
725 | */ | ||
726 | len = sizeof (enc_oid); | ||
727 | result = | ||
728 | asn1_read_value (pkcs8_asn, "encryptionAlgorithm.algorithm", | ||
729 | enc_oid, &len); | ||
730 | if (result != ASN1_SUCCESS) | ||
731 | { | ||
732 | gnutls_assert (); | ||
733 | goto error; | ||
734 | } | ||
735 | |||
736 | if ((result = check_schema (enc_oid)) < 0) | ||
737 | { | ||
738 | gnutls_assert (); | ||
739 | goto error; | ||
740 | } | ||
741 | |||
742 | schema = result; | ||
743 | |||
744 | /* Get the DER encoding of the parameters. | ||
745 | */ | ||
746 | result = | ||
747 | asn1_der_decoding_startEnd (pkcs8_asn, raw_key->data, | ||
748 | raw_key->size, | ||
749 | "encryptionAlgorithm.parameters", | ||
750 | ¶ms_start, ¶ms_end); | ||
751 | if (result != ASN1_SUCCESS) | ||
752 | { | ||
753 | gnutls_assert (); | ||
754 | result = _gnutls_asn2err (result); | ||
755 | goto error; | ||
756 | } | ||
757 | params_len = params_end - params_start + 1; | ||
758 | |||
759 | result = | ||
760 | read_pkcs_schema_params (schema, password, | ||
761 | &raw_key->data[params_start], | ||
762 | params_len, &kdf_params, &enc_params); | ||
763 | |||
764 | /* Parameters have been decoded. Now | ||
765 | * decrypt the EncryptedData. | ||
766 | */ | ||
767 | result = | ||
768 | decrypt_data (schema, pkcs8_asn, "encryptedData", password, | ||
769 | &kdf_params, &enc_params, &tmp); | ||
770 | if (result < 0) | ||
771 | { | ||
772 | gnutls_assert (); | ||
773 | goto error; | ||
774 | } | ||
775 | |||
776 | asn1_delete_structure (&pkcs8_asn); | ||
777 | |||
778 | result = decode_private_key_info (&tmp, pkey); | ||
779 | _gnutls_free_datum (&tmp); | ||
780 | |||
781 | if (result < 0) | ||
782 | { | ||
783 | /* We've gotten this far. In the real world it's almost certain | ||
784 | * that we're dealing with a good file, but wrong password. | ||
785 | * Sadly like 90% of random data is somehow valid DER for the | ||
786 | * a first small number of bytes, so no easy way to guarantee. */ | ||
787 | if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND || | ||
788 | result == GNUTLS_E_ASN1_IDENTIFIER_NOT_FOUND || | ||
789 | result == GNUTLS_E_ASN1_DER_ERROR || | ||
790 | result == GNUTLS_E_ASN1_VALUE_NOT_FOUND || | ||
791 | result == GNUTLS_E_ASN1_GENERIC_ERROR || | ||
792 | result == GNUTLS_E_ASN1_VALUE_NOT_VALID || | ||
793 | result == GNUTLS_E_ASN1_TAG_ERROR || | ||
794 | result == GNUTLS_E_ASN1_TAG_IMPLICIT || | ||
795 | result == GNUTLS_E_ASN1_TYPE_ANY_ERROR || | ||
796 | result == GNUTLS_E_ASN1_SYNTAX_ERROR || | ||
797 | result == GNUTLS_E_ASN1_DER_OVERFLOW) | ||
798 | { | ||
799 | result = GNUTLS_E_DECRYPTION_FAILED; | ||
800 | } | ||
801 | |||
802 | gnutls_assert (); | ||
803 | goto error; | ||
804 | } | ||
805 | |||
806 | return 0; | ||
807 | |||
808 | error: | ||
809 | asn1_delete_structure (&pbes2_asn); | ||
810 | asn1_delete_structure (&pkcs8_asn); | ||
811 | return result; | ||
812 | } | ||
813 | |||
814 | /* Decodes an RSA privateKey from a PKCS8 structure. | ||
815 | */ | ||
816 | static int | ||
817 | _decode_pkcs8_rsa_key (ASN1_TYPE pkcs8_asn, gnutls_x509_privkey pkey) | ||
818 | { | ||
819 | int ret; | ||
820 | gnutls_datum tmp; | ||
821 | |||
822 | ret = _gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp, 0); | ||
823 | if (ret < 0) | ||
824 | { | ||
825 | gnutls_assert (); | ||
826 | goto error; | ||
827 | } | ||
828 | |||
829 | pkey->key = _gnutls_privkey_decode_pkcs1_rsa_key (&tmp, pkey); | ||
830 | _gnutls_free_datum (&tmp); | ||
831 | if (pkey->key == NULL) | ||
832 | { | ||
833 | gnutls_assert (); | ||
834 | goto error; | ||
835 | } | ||
836 | |||
837 | return 0; | ||
838 | |||
839 | error: | ||
840 | gnutls_x509_privkey_deinit (pkey); | ||
841 | return ret; | ||
842 | } | ||
843 | |||
844 | /* Decodes an DSA privateKey and params from a PKCS8 structure. | ||
845 | */ | ||
846 | static int | ||
847 | _decode_pkcs8_dsa_key (ASN1_TYPE pkcs8_asn, gnutls_x509_privkey pkey) | ||
848 | { | ||
849 | int ret; | ||
850 | gnutls_datum tmp; | ||
851 | |||
852 | ret = _gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp, 0); | ||
853 | if (ret < 0) | ||
854 | { | ||
855 | gnutls_assert (); | ||
856 | goto error; | ||
857 | } | ||
858 | |||
859 | ret = _gnutls_x509_read_der_int (tmp.data, tmp.size, &pkey->params[4]); | ||
860 | _gnutls_free_datum (&tmp); | ||
861 | |||
862 | if (ret < 0) | ||
863 | { | ||
864 | gnutls_assert (); | ||
865 | goto error; | ||
866 | } | ||
867 | |||
868 | ret = | ||
869 | _gnutls_x509_read_value (pkcs8_asn, "privateKeyAlgorithm.parameters", | ||
870 | &tmp, 0); | ||
871 | if (ret < 0) | ||
872 | { | ||
873 | gnutls_assert (); | ||
874 | goto error; | ||
875 | } | ||
876 | |||
877 | ret = _gnutls_x509_read_dsa_params (tmp.data, tmp.size, pkey->params); | ||
878 | _gnutls_free_datum (&tmp); | ||
879 | if (ret < 0) | ||
880 | { | ||
881 | gnutls_assert (); | ||
882 | goto error; | ||
883 | } | ||
884 | |||
885 | /* the public key can be generated as g^x mod p */ | ||
886 | pkey->params[3] = _gnutls_mpi_alloc_like (pkey->params[0]); | ||
887 | if (pkey->params[3] == NULL) | ||
888 | { | ||
889 | gnutls_assert (); | ||
890 | goto error; | ||
891 | } | ||
892 | |||
893 | _gnutls_mpi_powm (pkey->params[3], pkey->params[2], pkey->params[4], | ||
894 | pkey->params[0]); | ||
895 | |||
896 | if (!pkey->crippled) | ||
897 | { | ||
898 | ret = _gnutls_asn1_encode_dsa (&pkey->key, pkey->params); | ||
899 | if (ret < 0) | ||
900 | { | ||
901 | gnutls_assert (); | ||
902 | goto error; | ||
903 | } | ||
904 | } | ||
905 | |||
906 | pkey->params_size = DSA_PRIVATE_PARAMS; | ||
907 | |||
908 | return 0; | ||
909 | |||
910 | error: | ||
911 | gnutls_x509_privkey_deinit (pkey); | ||
912 | return ret; | ||
913 | } | ||
914 | |||
915 | static int | ||
916 | decode_private_key_info (const gnutls_datum_t * der, | ||
917 | gnutls_x509_privkey_t pkey) | ||
918 | { | ||
919 | int result, len; | ||
920 | opaque oid[64]; | ||
921 | ASN1_TYPE pkcs8_asn = ASN1_TYPE_EMPTY; | ||
922 | |||
923 | if ((result = | ||
924 | asn1_create_element (_gnutls_get_pkix (), | ||
925 | "PKIX1.pkcs-8-PrivateKeyInfo", | ||
926 | &pkcs8_asn)) != ASN1_SUCCESS) | ||
927 | { | ||
928 | gnutls_assert (); | ||
929 | result = _gnutls_asn2err (result); | ||
930 | goto error; | ||
931 | } | ||
932 | |||
933 | result = asn1_der_decoding (&pkcs8_asn, der->data, der->size, NULL); | ||
934 | if (result != ASN1_SUCCESS) | ||
935 | { | ||
936 | gnutls_assert (); | ||
937 | result = _gnutls_asn2err (result); | ||
938 | goto error; | ||
939 | } | ||
940 | |||
941 | /* Check the private key algorithm OID | ||
942 | */ | ||
943 | len = sizeof (oid); | ||
944 | result = | ||
945 | asn1_read_value (pkcs8_asn, "privateKeyAlgorithm.algorithm", oid, &len); | ||
946 | if (result != ASN1_SUCCESS) | ||
947 | { | ||
948 | gnutls_assert (); | ||
949 | result = _gnutls_asn2err (result); | ||
950 | goto error; | ||
951 | } | ||
952 | |||
953 | /* we only support RSA and DSA private keys. | ||
954 | */ | ||
955 | if (strcmp (oid, PK_PKIX1_RSA_OID) == 0) | ||
956 | pkey->pk_algorithm = GNUTLS_PK_RSA; | ||
957 | else | ||
958 | { | ||
959 | gnutls_assert (); | ||
960 | _gnutls_x509_log | ||
961 | ("PKCS #8 private key OID '%s' is unsupported.\n", oid); | ||
962 | result = GNUTLS_E_UNKNOWN_PK_ALGORITHM; | ||
963 | goto error; | ||
964 | } | ||
965 | |||
966 | /* Get the DER encoding of the actual private key. | ||
967 | */ | ||
968 | |||
969 | if (pkey->pk_algorithm == GNUTLS_PK_RSA) | ||
970 | result = _decode_pkcs8_rsa_key (pkcs8_asn, pkey); | ||
971 | if (result < 0) | ||
972 | { | ||
973 | gnutls_assert (); | ||
974 | return result; | ||
975 | } | ||
976 | |||
977 | result = 0; | ||
978 | |||
979 | error: | ||
980 | asn1_delete_structure (&pkcs8_asn); | ||
981 | |||
982 | return result; | ||
983 | |||
984 | } | ||
985 | |||
986 | /** | ||
987 | * gnutls_x509_privkey_import_pkcs8 - This function will import a DER or PEM PKCS8 encoded key | ||
988 | * @key: The structure to store the parsed key | ||
989 | * @data: The DER or PEM encoded key. | ||
990 | * @format: One of DER or PEM | ||
991 | * @password: the password to decrypt the key (if it is encrypted). | ||
992 | * @flags: 0 if encrypted or GNUTLS_PKCS_PLAIN if not encrypted. | ||
993 | * | ||
994 | * This function will convert the given DER or PEM encoded PKCS8 2.0 encrypted key | ||
995 | * to the native gnutls_x509_privkey_t format. The output will be stored in @key. | ||
996 | * Both RSA and DSA keys can be imported, and flags can only be used to indicate | ||
997 | * an unencrypted key. | ||
998 | * | ||
999 | * The @password can be either ASCII or UTF-8 in the default PBES2 | ||
1000 | * encryption schemas, or ASCII for the PKCS12 schemas. | ||
1001 | * | ||
1002 | * If the Certificate is PEM encoded it should have a header of "ENCRYPTED PRIVATE KEY", | ||
1003 | * or "PRIVATE KEY". You only need to specify the flags if the key is DER encoded, since | ||
1004 | * in that case the encryption status cannot be auto-detected. | ||
1005 | * | ||
1006 | * Returns 0 on success. | ||
1007 | * | ||
1008 | **/ | ||
1009 | int | ||
1010 | gnutls_x509_privkey_import_pkcs8 (gnutls_x509_privkey_t key, | ||
1011 | const gnutls_datum_t * data, | ||
1012 | gnutls_x509_crt_fmt_t format, | ||
1013 | const char *password, unsigned int flags) | ||
1014 | { | ||
1015 | int result = 0, need_free = 0; | ||
1016 | gnutls_datum_t _data; | ||
1017 | |||
1018 | if (key == NULL) | ||
1019 | { | ||
1020 | gnutls_assert (); | ||
1021 | return GNUTLS_E_INVALID_REQUEST; | ||
1022 | } | ||
1023 | |||
1024 | _data.data = data->data; | ||
1025 | _data.size = data->size; | ||
1026 | |||
1027 | key->pk_algorithm = GNUTLS_PK_UNKNOWN; | ||
1028 | |||
1029 | /* If the Certificate is in PEM format then decode it | ||
1030 | */ | ||
1031 | if (format == GNUTLS_X509_FMT_PEM) | ||
1032 | { | ||
1033 | opaque *out; | ||
1034 | |||
1035 | /* Try the first header | ||
1036 | */ | ||
1037 | result = | ||
1038 | _gnutls_fbase64_decode (PEM_UNENCRYPTED_PKCS8, | ||
1039 | data->data, data->size, &out); | ||
1040 | |||
1041 | if (result < 0) | ||
1042 | { /* Try the encrypted header | ||
1043 | */ | ||
1044 | result = | ||
1045 | _gnutls_fbase64_decode (PEM_PKCS8, data->data, data->size, &out); | ||
1046 | |||
1047 | if (result <= 0) | ||
1048 | { | ||
1049 | if (result == 0) | ||
1050 | result = GNUTLS_E_INTERNAL_ERROR; | ||
1051 | gnutls_assert (); | ||
1052 | return result; | ||
1053 | } | ||
1054 | } | ||
1055 | else if (flags == 0) | ||
1056 | flags |= GNUTLS_PKCS_PLAIN; | ||
1057 | |||
1058 | _data.data = out; | ||
1059 | _data.size = result; | ||
1060 | |||
1061 | need_free = 1; | ||
1062 | } | ||
1063 | |||
1064 | if (flags & GNUTLS_PKCS_PLAIN) | ||
1065 | { | ||
1066 | result = decode_private_key_info (&_data, key); | ||
1067 | } | ||
1068 | else | ||
1069 | { /* encrypted. */ | ||
1070 | result = decode_pkcs8_key (&_data, password, key); | ||
1071 | } | ||
1072 | |||
1073 | if (result < 0) | ||
1074 | { | ||
1075 | gnutls_assert (); | ||
1076 | goto cleanup; | ||
1077 | } | ||
1078 | |||
1079 | if (need_free) | ||
1080 | _gnutls_free_datum (&_data); | ||
1081 | |||
1082 | /* The key has now been decoded. | ||
1083 | */ | ||
1084 | |||
1085 | return 0; | ||
1086 | |||
1087 | cleanup: | ||
1088 | key->pk_algorithm = GNUTLS_PK_UNKNOWN; | ||
1089 | if (need_free) | ||
1090 | _gnutls_free_datum (&_data); | ||
1091 | return result; | ||
1092 | } | ||
1093 | |||
1094 | /* Reads the PBKDF2 parameters. | ||
1095 | */ | ||
1096 | static int | ||
1097 | read_pbkdf2_params (ASN1_TYPE pbes2_asn, | ||
1098 | const gnutls_datum_t * der, struct pbkdf2_params *params) | ||
1099 | { | ||
1100 | int params_start, params_end; | ||
1101 | int params_len, len, result; | ||
1102 | ASN1_TYPE pbkdf2_asn = ASN1_TYPE_EMPTY; | ||
1103 | char oid[64]; | ||
1104 | |||
1105 | memset (params, 0, sizeof (params)); | ||
1106 | |||
1107 | /* Check the key derivation algorithm | ||
1108 | */ | ||
1109 | len = sizeof (oid); | ||
1110 | result = | ||
1111 | asn1_read_value (pbes2_asn, "keyDerivationFunc.algorithm", oid, &len); | ||
1112 | if (result != ASN1_SUCCESS) | ||
1113 | { | ||
1114 | gnutls_assert (); | ||
1115 | return _gnutls_asn2err (result); | ||
1116 | } | ||
1117 | _gnutls_hard_log ("keyDerivationFunc.algorithm: %s\n", oid); | ||
1118 | |||
1119 | if (strcmp (oid, PBKDF2_OID) != 0) | ||
1120 | { | ||
1121 | gnutls_assert (); | ||
1122 | _gnutls_x509_log | ||
1123 | ("PKCS #8 key derivation OID '%s' is unsupported.\n", oid); | ||
1124 | return _gnutls_asn2err (result); | ||
1125 | } | ||
1126 | |||
1127 | result = | ||
1128 | asn1_der_decoding_startEnd (pbes2_asn, der->data, der->size, | ||
1129 | "keyDerivationFunc.parameters", | ||
1130 | ¶ms_start, ¶ms_end); | ||
1131 | if (result != ASN1_SUCCESS) | ||
1132 | { | ||
1133 | gnutls_assert (); | ||
1134 | return _gnutls_asn2err (result); | ||
1135 | } | ||
1136 | params_len = params_end - params_start + 1; | ||
1137 | |||
1138 | /* Now check the key derivation and the encryption | ||
1139 | * functions. | ||
1140 | */ | ||
1141 | if ((result = | ||
1142 | asn1_create_element (_gnutls_get_pkix (), | ||
1143 | "PKIX1.pkcs-5-PBKDF2-params", | ||
1144 | &pbkdf2_asn)) != ASN1_SUCCESS) | ||
1145 | { | ||
1146 | gnutls_assert (); | ||
1147 | return _gnutls_asn2err (result); | ||
1148 | } | ||
1149 | |||
1150 | result = | ||
1151 | asn1_der_decoding (&pbkdf2_asn, &der->data[params_start], | ||
1152 | params_len, NULL); | ||
1153 | if (result != ASN1_SUCCESS) | ||
1154 | { | ||
1155 | gnutls_assert (); | ||
1156 | result = _gnutls_asn2err (result); | ||
1157 | goto error; | ||
1158 | } | ||
1159 | |||
1160 | /* read the salt */ | ||
1161 | params->salt_size = sizeof (params->salt); | ||
1162 | result = | ||
1163 | asn1_read_value (pbkdf2_asn, "salt.specified", params->salt, | ||
1164 | ¶ms->salt_size); | ||
1165 | if (result != ASN1_SUCCESS) | ||
1166 | { | ||
1167 | gnutls_assert (); | ||
1168 | result = _gnutls_asn2err (result); | ||
1169 | goto error; | ||
1170 | } | ||
1171 | _gnutls_hard_log ("salt.specified.size: %d\n", params->salt_size); | ||
1172 | |||
1173 | /* read the iteration count | ||
1174 | */ | ||
1175 | result = | ||
1176 | _gnutls_x509_read_uint (pbkdf2_asn, "iterationCount", | ||
1177 | ¶ms->iter_count); | ||
1178 | if (result != ASN1_SUCCESS) | ||
1179 | { | ||
1180 | gnutls_assert (); | ||
1181 | goto error; | ||
1182 | } | ||
1183 | _gnutls_hard_log ("iterationCount: %d\n", params->iter_count); | ||
1184 | |||
1185 | /* read the keylength, if it is set. | ||
1186 | */ | ||
1187 | result = | ||
1188 | _gnutls_x509_read_uint (pbkdf2_asn, "keyLength", ¶ms->key_size); | ||
1189 | if (result < 0) | ||
1190 | { | ||
1191 | params->key_size = 0; | ||
1192 | } | ||
1193 | _gnutls_hard_log ("keyLength: %d\n", params->key_size); | ||
1194 | |||
1195 | /* We don't read the PRF. We only use the default. | ||
1196 | */ | ||
1197 | |||
1198 | return 0; | ||
1199 | |||
1200 | error: | ||
1201 | asn1_delete_structure (&pbkdf2_asn); | ||
1202 | return result; | ||
1203 | |||
1204 | } | ||
1205 | |||
1206 | /* Reads the PBE parameters from PKCS-12 schemas (*&#%*&#% RSA). | ||
1207 | */ | ||
1208 | static int | ||
1209 | read_pkcs12_kdf_params (ASN1_TYPE pbes2_asn, struct pbkdf2_params *params) | ||
1210 | { | ||
1211 | int result; | ||
1212 | |||
1213 | memset (params, 0, sizeof (params)); | ||
1214 | |||
1215 | /* read the salt */ | ||
1216 | params->salt_size = sizeof (params->salt); | ||
1217 | result = | ||
1218 | asn1_read_value (pbes2_asn, "salt", params->salt, ¶ms->salt_size); | ||
1219 | if (result != ASN1_SUCCESS) | ||
1220 | { | ||
1221 | gnutls_assert (); | ||
1222 | result = _gnutls_asn2err (result); | ||
1223 | goto error; | ||
1224 | } | ||
1225 | _gnutls_hard_log ("salt.size: %d\n", params->salt_size); | ||
1226 | |||
1227 | /* read the iteration count | ||
1228 | */ | ||
1229 | result = | ||
1230 | _gnutls_x509_read_uint (pbes2_asn, "iterations", ¶ms->iter_count); | ||
1231 | if (result != ASN1_SUCCESS) | ||
1232 | { | ||
1233 | gnutls_assert (); | ||
1234 | goto error; | ||
1235 | } | ||
1236 | _gnutls_hard_log ("iterationCount: %d\n", params->iter_count); | ||
1237 | |||
1238 | params->key_size = 0; | ||
1239 | |||
1240 | return 0; | ||
1241 | |||
1242 | error: | ||
1243 | return result; | ||
1244 | |||
1245 | } | ||
1246 | |||
1247 | /* Writes the PBE parameters for PKCS-12 schemas. | ||
1248 | */ | ||
1249 | static int | ||
1250 | write_pkcs12_kdf_params (ASN1_TYPE pbes2_asn, | ||
1251 | const struct pbkdf2_params *kdf_params) | ||
1252 | { | ||
1253 | int result; | ||
1254 | |||
1255 | /* write the salt | ||
1256 | */ | ||
1257 | result = | ||
1258 | asn1_write_value (pbes2_asn, "salt", | ||
1259 | kdf_params->salt, kdf_params->salt_size); | ||
1260 | if (result != ASN1_SUCCESS) | ||
1261 | { | ||
1262 | gnutls_assert (); | ||
1263 | result = _gnutls_asn2err (result); | ||
1264 | goto error; | ||
1265 | } | ||
1266 | _gnutls_hard_log ("salt.size: %d\n", kdf_params->salt_size); | ||
1267 | |||
1268 | /* write the iteration count | ||
1269 | */ | ||
1270 | result = | ||
1271 | _gnutls_x509_write_uint32 (pbes2_asn, "iterations", | ||
1272 | kdf_params->iter_count); | ||
1273 | if (result < 0) | ||
1274 | { | ||
1275 | gnutls_assert (); | ||
1276 | goto error; | ||
1277 | } | ||
1278 | _gnutls_hard_log ("iterationCount: %d\n", kdf_params->iter_count); | ||
1279 | |||
1280 | return 0; | ||
1281 | |||
1282 | error: | ||
1283 | return result; | ||
1284 | |||
1285 | } | ||
1286 | |||
1287 | /* Converts an OID to a gnutls cipher type. | ||
1288 | */ | ||
1289 | inline static int | ||
1290 | oid2cipher (const char *oid, gnutls_cipher_algorithm_t * algo) | ||
1291 | { | ||
1292 | |||
1293 | *algo = 0; | ||
1294 | |||
1295 | if (strcmp (oid, DES_EDE3_CBC_OID) == 0) | ||
1296 | { | ||
1297 | *algo = GNUTLS_CIPHER_3DES_CBC; | ||
1298 | return 0; | ||
1299 | } | ||
1300 | |||
1301 | if (strcmp (oid, DES_CBC_OID) == 0) | ||
1302 | { | ||
1303 | *algo = GNUTLS_CIPHER_DES_CBC; | ||
1304 | return 0; | ||
1305 | } | ||
1306 | |||
1307 | _gnutls_x509_log ("PKCS #8 encryption OID '%s' is unsupported.\n", oid); | ||
1308 | return GNUTLS_E_UNKNOWN_CIPHER_TYPE; | ||
1309 | } | ||
1310 | |||
1311 | static int | ||
1312 | read_pbe_enc_params (ASN1_TYPE pbes2_asn, | ||
1313 | const gnutls_datum_t * der, | ||
1314 | struct pbe_enc_params *params) | ||
1315 | { | ||
1316 | int params_start, params_end; | ||
1317 | int params_len, len, result; | ||
1318 | ASN1_TYPE pbe_asn = ASN1_TYPE_EMPTY; | ||
1319 | char oid[64]; | ||
1320 | |||
1321 | memset (params, 0, sizeof (params)); | ||
1322 | |||
1323 | /* Check the encryption algorithm | ||
1324 | */ | ||
1325 | len = sizeof (oid); | ||
1326 | result = | ||
1327 | asn1_read_value (pbes2_asn, "encryptionScheme.algorithm", oid, &len); | ||
1328 | if (result != ASN1_SUCCESS) | ||
1329 | { | ||
1330 | gnutls_assert (); | ||
1331 | goto error; | ||
1332 | } | ||
1333 | _gnutls_hard_log ("encryptionScheme.algorithm: %s\n", oid); | ||
1334 | |||
1335 | if ((result = oid2cipher (oid, ¶ms->cipher)) < 0) | ||
1336 | { | ||
1337 | gnutls_assert (); | ||
1338 | goto error; | ||
1339 | } | ||
1340 | |||
1341 | result = | ||
1342 | asn1_der_decoding_startEnd (pbes2_asn, der->data, der->size, | ||
1343 | "encryptionScheme.parameters", | ||
1344 | ¶ms_start, ¶ms_end); | ||
1345 | if (result != ASN1_SUCCESS) | ||
1346 | { | ||
1347 | gnutls_assert (); | ||
1348 | return _gnutls_asn2err (result); | ||
1349 | } | ||
1350 | params_len = params_end - params_start + 1; | ||
1351 | |||
1352 | /* Now check the encryption parameters. | ||
1353 | */ | ||
1354 | if ((result = | ||
1355 | asn1_create_element (_gnutls_get_pkix (), | ||
1356 | "PKIX1.pkcs-5-des-EDE3-CBC-params", | ||
1357 | &pbe_asn)) != ASN1_SUCCESS) | ||
1358 | { | ||
1359 | gnutls_assert (); | ||
1360 | return _gnutls_asn2err (result); | ||
1361 | } | ||
1362 | |||
1363 | result = | ||
1364 | asn1_der_decoding (&pbe_asn, &der->data[params_start], params_len, NULL); | ||
1365 | if (result != ASN1_SUCCESS) | ||
1366 | { | ||
1367 | gnutls_assert (); | ||
1368 | result = _gnutls_asn2err (result); | ||
1369 | goto error; | ||
1370 | } | ||
1371 | |||
1372 | /* read the IV */ | ||
1373 | params->iv_size = sizeof (params->iv); | ||
1374 | result = asn1_read_value (pbe_asn, "", params->iv, ¶ms->iv_size); | ||
1375 | if (result != ASN1_SUCCESS) | ||
1376 | { | ||
1377 | gnutls_assert (); | ||
1378 | result = _gnutls_asn2err (result); | ||
1379 | goto error; | ||
1380 | } | ||
1381 | _gnutls_hard_log ("IV.size: %d\n", params->iv_size); | ||
1382 | |||
1383 | return 0; | ||
1384 | |||
1385 | error: | ||
1386 | asn1_delete_structure (&pbe_asn); | ||
1387 | return result; | ||
1388 | |||
1389 | } | ||
1390 | |||
1391 | static int | ||
1392 | decrypt_data (schema_id schema, ASN1_TYPE pkcs8_asn, | ||
1393 | const char *root, const char *password, | ||
1394 | const struct pbkdf2_params *kdf_params, | ||
1395 | const struct pbe_enc_params *enc_params, | ||
1396 | gnutls_datum_t * decrypted_data) | ||
1397 | { | ||
1398 | int result; | ||
1399 | int data_size; | ||
1400 | opaque *data = NULL, *key = NULL; | ||
1401 | gnutls_datum_t dkey, d_iv; | ||
1402 | cipher_hd_t ch = NULL; | ||
1403 | int key_size; | ||
1404 | |||
1405 | data_size = 0; | ||
1406 | result = asn1_read_value (pkcs8_asn, root, NULL, &data_size); | ||
1407 | if (result != ASN1_MEM_ERROR) | ||
1408 | { | ||
1409 | gnutls_assert (); | ||
1410 | return _gnutls_asn2err (result); | ||
1411 | } | ||
1412 | |||
1413 | data = gnutls_malloc (data_size); | ||
1414 | if (data == NULL) | ||
1415 | { | ||
1416 | gnutls_assert (); | ||
1417 | return GNUTLS_E_MEMORY_ERROR; | ||
1418 | } | ||
1419 | |||
1420 | result = asn1_read_value (pkcs8_asn, root, data, &data_size); | ||
1421 | if (result != ASN1_SUCCESS) | ||
1422 | { | ||
1423 | gnutls_assert (); | ||
1424 | result = _gnutls_asn2err (result); | ||
1425 | goto error; | ||
1426 | } | ||
1427 | |||
1428 | if (kdf_params->key_size == 0) | ||
1429 | { | ||
1430 | key_size = gnutls_cipher_get_key_size (enc_params->cipher); | ||
1431 | } | ||
1432 | else | ||
1433 | key_size = kdf_params->key_size; | ||
1434 | |||
1435 | key = gnutls_alloca (key_size); | ||
1436 | if (key == NULL) | ||
1437 | { | ||
1438 | gnutls_assert (); | ||
1439 | result = GNUTLS_E_MEMORY_ERROR; | ||
1440 | goto error; | ||
1441 | } | ||
1442 | |||
1443 | /* generate the key | ||
1444 | */ | ||
1445 | if (schema == PBES2) | ||
1446 | { | ||
1447 | result = gc_pbkdf2_sha1 (password, strlen (password), | ||
1448 | kdf_params->salt, kdf_params->salt_size, | ||
1449 | kdf_params->iter_count, key, key_size); | ||
1450 | |||
1451 | if (result != GC_OK) | ||
1452 | { | ||
1453 | gnutls_assert (); | ||
1454 | result = GNUTLS_E_DECRYPTION_FAILED; | ||
1455 | goto error; | ||
1456 | } | ||
1457 | } | ||
1458 | else | ||
1459 | { | ||
1460 | result = | ||
1461 | _pkcs12_string_to_key (1 /*KEY*/, kdf_params->salt, | ||
1462 | kdf_params->salt_size, | ||
1463 | kdf_params->iter_count, password, | ||
1464 | key_size, key); | ||
1465 | |||
1466 | if (result < 0) | ||
1467 | { | ||
1468 | gnutls_assert (); | ||
1469 | goto error; | ||
1470 | } | ||
1471 | } | ||
1472 | |||
1473 | /* do the decryption. | ||
1474 | */ | ||
1475 | dkey.data = key; | ||
1476 | dkey.size = key_size; | ||
1477 | |||
1478 | d_iv.data = (opaque *) enc_params->iv; | ||
1479 | d_iv.size = enc_params->iv_size; | ||
1480 | ch = _gnutls_cipher_init (enc_params->cipher, &dkey, &d_iv); | ||
1481 | |||
1482 | gnutls_afree (key); | ||
1483 | key = NULL; | ||
1484 | |||
1485 | if (ch == NULL) | ||
1486 | { | ||
1487 | gnutls_assert (); | ||
1488 | result = GNUTLS_E_DECRYPTION_FAILED; | ||
1489 | goto error; | ||
1490 | } | ||
1491 | |||
1492 | result = _gnutls_cipher_decrypt (ch, data, data_size); | ||
1493 | if (result < 0) | ||
1494 | { | ||
1495 | gnutls_assert (); | ||
1496 | goto error; | ||
1497 | } | ||
1498 | |||
1499 | decrypted_data->data = data; | ||
1500 | |||
1501 | if (_gnutls_cipher_get_block_size (enc_params->cipher) != 1) | ||
1502 | decrypted_data->size = data_size - data[data_size - 1]; | ||
1503 | else | ||
1504 | decrypted_data->size = data_size; | ||
1505 | |||
1506 | _gnutls_cipher_deinit (ch); | ||
1507 | |||
1508 | return 0; | ||
1509 | |||
1510 | error: | ||
1511 | gnutls_free (data); | ||
1512 | gnutls_afree (key); | ||
1513 | if (ch != NULL) | ||
1514 | _gnutls_cipher_deinit (ch); | ||
1515 | return result; | ||
1516 | } | ||
1517 | |||
1518 | /* Writes the PBKDF2 parameters. | ||
1519 | */ | ||
1520 | static int | ||
1521 | write_pbkdf2_params (ASN1_TYPE pbes2_asn, | ||
1522 | const struct pbkdf2_params *kdf_params) | ||
1523 | { | ||
1524 | int result; | ||
1525 | ASN1_TYPE pbkdf2_asn = ASN1_TYPE_EMPTY; | ||
1526 | opaque tmp[64]; | ||
1527 | |||
1528 | /* Write the key derivation algorithm | ||
1529 | */ | ||
1530 | result = | ||
1531 | asn1_write_value (pbes2_asn, "keyDerivationFunc.algorithm", | ||
1532 | PBKDF2_OID, 1); | ||
1533 | if (result != ASN1_SUCCESS) | ||
1534 | { | ||
1535 | gnutls_assert (); | ||
1536 | return _gnutls_asn2err (result); | ||
1537 | } | ||
1538 | |||
1539 | /* Now write the key derivation and the encryption | ||
1540 | * functions. | ||
1541 | */ | ||
1542 | if ((result = | ||
1543 | asn1_create_element (_gnutls_get_pkix (), | ||
1544 | "PKIX1.pkcs-5-PBKDF2-params", | ||
1545 | &pbkdf2_asn)) != ASN1_SUCCESS) | ||
1546 | { | ||
1547 | gnutls_assert (); | ||
1548 | return _gnutls_asn2err (result); | ||
1549 | } | ||
1550 | |||
1551 | result = asn1_write_value (pbkdf2_asn, "salt", "specified", 1); | ||
1552 | if (result != ASN1_SUCCESS) | ||
1553 | { | ||
1554 | gnutls_assert (); | ||
1555 | result = _gnutls_asn2err (result); | ||
1556 | goto error; | ||
1557 | } | ||
1558 | |||
1559 | /* write the salt | ||
1560 | */ | ||
1561 | result = | ||
1562 | asn1_write_value (pbkdf2_asn, "salt.specified", | ||
1563 | kdf_params->salt, kdf_params->salt_size); | ||
1564 | if (result != ASN1_SUCCESS) | ||
1565 | { | ||
1566 | gnutls_assert (); | ||
1567 | result = _gnutls_asn2err (result); | ||
1568 | goto error; | ||
1569 | } | ||
1570 | _gnutls_hard_log ("salt.specified.size: %d\n", kdf_params->salt_size); | ||
1571 | |||
1572 | /* write the iteration count | ||
1573 | */ | ||
1574 | _gnutls_write_uint32 (kdf_params->iter_count, tmp); | ||
1575 | |||
1576 | result = asn1_write_value (pbkdf2_asn, "iterationCount", tmp, 4); | ||
1577 | if (result != ASN1_SUCCESS) | ||
1578 | { | ||
1579 | gnutls_assert (); | ||
1580 | result = _gnutls_asn2err (result); | ||
1581 | goto error; | ||
1582 | } | ||
1583 | _gnutls_hard_log ("iterationCount: %d\n", kdf_params->iter_count); | ||
1584 | |||
1585 | /* write the keylength, if it is set. | ||
1586 | */ | ||
1587 | result = asn1_write_value (pbkdf2_asn, "keyLength", NULL, 0); | ||
1588 | if (result != ASN1_SUCCESS) | ||
1589 | { | ||
1590 | gnutls_assert (); | ||
1591 | result = _gnutls_asn2err (result); | ||
1592 | goto error; | ||
1593 | } | ||
1594 | |||
1595 | /* We write an emptry prf. | ||
1596 | */ | ||
1597 | result = asn1_write_value (pbkdf2_asn, "prf", NULL, 0); | ||
1598 | if (result != ASN1_SUCCESS) | ||
1599 | { | ||
1600 | gnutls_assert (); | ||
1601 | result = _gnutls_asn2err (result); | ||
1602 | goto error; | ||
1603 | } | ||
1604 | |||
1605 | /* now encode them an put the DER output | ||
1606 | * in the keyDerivationFunc.parameters | ||
1607 | */ | ||
1608 | result = _gnutls_x509_der_encode_and_copy (pbkdf2_asn, "", | ||
1609 | pbes2_asn, | ||
1610 | "keyDerivationFunc.parameters", | ||
1611 | 0); | ||
1612 | if (result < 0) | ||
1613 | { | ||
1614 | gnutls_assert (); | ||
1615 | goto error; | ||
1616 | } | ||
1617 | |||
1618 | return 0; | ||
1619 | |||
1620 | error: | ||
1621 | asn1_delete_structure (&pbkdf2_asn); | ||
1622 | return result; | ||
1623 | |||
1624 | } | ||
1625 | |||
1626 | static int | ||
1627 | write_pbe_enc_params (ASN1_TYPE pbes2_asn, | ||
1628 | const struct pbe_enc_params *params) | ||
1629 | { | ||
1630 | int result; | ||
1631 | ASN1_TYPE pbe_asn = ASN1_TYPE_EMPTY; | ||
1632 | |||
1633 | /* Write the encryption algorithm | ||
1634 | */ | ||
1635 | result = | ||
1636 | asn1_write_value (pbes2_asn, "encryptionScheme.algorithm", | ||
1637 | DES_EDE3_CBC_OID, 1); | ||
1638 | if (result != ASN1_SUCCESS) | ||
1639 | { | ||
1640 | gnutls_assert (); | ||
1641 | goto error; | ||
1642 | } | ||
1643 | _gnutls_hard_log ("encryptionScheme.algorithm: %s\n", DES_EDE3_CBC_OID); | ||
1644 | |||
1645 | /* Now check the encryption parameters. | ||
1646 | */ | ||
1647 | if ((result = | ||
1648 | asn1_create_element (_gnutls_get_pkix (), | ||
1649 | "PKIX1.pkcs-5-des-EDE3-CBC-params", | ||
1650 | &pbe_asn)) != ASN1_SUCCESS) | ||
1651 | { | ||
1652 | gnutls_assert (); | ||
1653 | return _gnutls_asn2err (result); | ||
1654 | } | ||
1655 | |||
1656 | /* read the salt */ | ||
1657 | result = asn1_write_value (pbe_asn, "", params->iv, params->iv_size); | ||
1658 | if (result != ASN1_SUCCESS) | ||
1659 | { | ||
1660 | gnutls_assert (); | ||
1661 | result = _gnutls_asn2err (result); | ||
1662 | goto error; | ||
1663 | } | ||
1664 | _gnutls_hard_log ("IV.size: %d\n", params->iv_size); | ||
1665 | |||
1666 | /* now encode them an put the DER output | ||
1667 | * in the encryptionScheme.parameters | ||
1668 | */ | ||
1669 | result = _gnutls_x509_der_encode_and_copy (pbe_asn, "", | ||
1670 | pbes2_asn, | ||
1671 | "encryptionScheme.parameters", | ||
1672 | 0); | ||
1673 | if (result < 0) | ||
1674 | { | ||
1675 | gnutls_assert (); | ||
1676 | goto error; | ||
1677 | } | ||
1678 | |||
1679 | return 0; | ||
1680 | |||
1681 | error: | ||
1682 | asn1_delete_structure (&pbe_asn); | ||
1683 | return result; | ||
1684 | |||
1685 | } | ||
1686 | |||
1687 | /* Generates a key and also stores the key parameters. | ||
1688 | */ | ||
1689 | static int | ||
1690 | generate_key (schema_id schema, | ||
1691 | const char *password, | ||
1692 | struct pbkdf2_params *kdf_params, | ||
1693 | struct pbe_enc_params *enc_params, gnutls_datum_t * key) | ||
1694 | { | ||
1695 | opaque rnd[2]; | ||
1696 | int ret; | ||
1697 | |||
1698 | /* We should use the flags here to use different | ||
1699 | * encryption algorithms etc. | ||
1700 | */ | ||
1701 | |||
1702 | if (schema == PKCS12_ARCFOUR_SHA1) | ||
1703 | enc_params->cipher = GNUTLS_CIPHER_ARCFOUR_128; | ||
1704 | else if (schema == PKCS12_3DES_SHA1) | ||
1705 | enc_params->cipher = GNUTLS_CIPHER_3DES_CBC; | ||
1706 | else if (schema == PKCS12_RC2_40_SHA1) | ||
1707 | enc_params->cipher = GNUTLS_CIPHER_RC2_40_CBC; | ||
1708 | |||
1709 | if (gc_pseudo_random (rnd, 2) != GC_OK) | ||
1710 | { | ||
1711 | gnutls_assert (); | ||
1712 | return GNUTLS_E_RANDOM_FAILED; | ||
1713 | } | ||
1714 | |||
1715 | /* generate salt */ | ||
1716 | |||
1717 | if (schema == PBES2) | ||
1718 | { | ||
1719 | kdf_params->salt_size = MIN (sizeof (kdf_params->salt), (unsigned) (10 + (rnd[1] % 10))); | ||
1720 | } | ||
1721 | else | ||
1722 | kdf_params->salt_size = 8; | ||
1723 | |||
1724 | if (gc_pseudo_random (kdf_params->salt, kdf_params->salt_size) != GC_OK) | ||
1725 | { | ||
1726 | gnutls_assert (); | ||
1727 | return GNUTLS_E_RANDOM_FAILED; | ||
1728 | } | ||
1729 | |||
1730 | kdf_params->iter_count = 256 + rnd[0]; | ||
1731 | key->size = kdf_params->key_size = | ||
1732 | gnutls_cipher_get_key_size (enc_params->cipher); | ||
1733 | |||
1734 | enc_params->iv_size = _gnutls_cipher_get_iv_size (enc_params->cipher); | ||
1735 | |||
1736 | key->data = gnutls_secure_malloc (key->size); | ||
1737 | if (key->data == NULL) | ||
1738 | { | ||
1739 | gnutls_assert (); | ||
1740 | return GNUTLS_E_MEMORY_ERROR; | ||
1741 | } | ||
1742 | |||
1743 | /* now generate the key. | ||
1744 | */ | ||
1745 | |||
1746 | if (schema == PBES2) | ||
1747 | { | ||
1748 | |||
1749 | ret = gc_pbkdf2_sha1 (password, strlen (password), | ||
1750 | kdf_params->salt, kdf_params->salt_size, | ||
1751 | kdf_params->iter_count, | ||
1752 | key->data, kdf_params->key_size); | ||
1753 | if (ret != GC_OK) | ||
1754 | { | ||
1755 | gnutls_assert (); | ||
1756 | return GNUTLS_E_ENCRYPTION_FAILED; | ||
1757 | } | ||
1758 | |||
1759 | if (enc_params->iv_size && | ||
1760 | gc_nonce (enc_params->iv, enc_params->iv_size) != GC_OK) | ||
1761 | { | ||
1762 | gnutls_assert (); | ||
1763 | return GNUTLS_E_RANDOM_FAILED; | ||
1764 | } | ||
1765 | } | ||
1766 | else | ||
1767 | { /* PKCS12 schemas */ | ||
1768 | ret = | ||
1769 | _pkcs12_string_to_key (1 /*KEY*/, kdf_params->salt, | ||
1770 | kdf_params->salt_size, | ||
1771 | kdf_params->iter_count, password, | ||
1772 | kdf_params->key_size, key->data); | ||
1773 | if (ret < 0) | ||
1774 | { | ||
1775 | gnutls_assert (); | ||
1776 | return ret; | ||
1777 | } | ||
1778 | |||
1779 | /* Now generate the IV | ||
1780 | */ | ||
1781 | if (enc_params->iv_size) | ||
1782 | { | ||
1783 | ret = | ||
1784 | _pkcs12_string_to_key (2 /*IV*/, kdf_params->salt, | ||
1785 | kdf_params->salt_size, | ||
1786 | kdf_params->iter_count, password, | ||
1787 | enc_params->iv_size, enc_params->iv); | ||
1788 | if (ret < 0) | ||
1789 | { | ||
1790 | gnutls_assert (); | ||
1791 | return ret; | ||
1792 | } | ||
1793 | } | ||
1794 | } | ||
1795 | |||
1796 | return 0; | ||
1797 | } | ||
1798 | |||
1799 | /* Encodes the parameters to be written in the encryptionAlgorithm.parameters | ||
1800 | * part. | ||
1801 | */ | ||
1802 | static int | ||
1803 | write_schema_params (schema_id schema, ASN1_TYPE pkcs8_asn, | ||
1804 | const char *where, | ||
1805 | const struct pbkdf2_params *kdf_params, | ||
1806 | const struct pbe_enc_params *enc_params) | ||
1807 | { | ||
1808 | int result; | ||
1809 | ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY; | ||
1810 | |||
1811 | if (schema == PBES2) | ||
1812 | { | ||
1813 | if ((result = | ||
1814 | asn1_create_element (_gnutls_get_pkix (), | ||
1815 | "PKIX1.pkcs-5-PBES2-params", | ||
1816 | &pbes2_asn)) != ASN1_SUCCESS) | ||
1817 | { | ||
1818 | gnutls_assert (); | ||
1819 | return _gnutls_asn2err (result); | ||
1820 | } | ||
1821 | |||
1822 | result = write_pbkdf2_params (pbes2_asn, kdf_params); | ||
1823 | if (result < 0) | ||
1824 | { | ||
1825 | gnutls_assert (); | ||
1826 | goto error; | ||
1827 | } | ||
1828 | |||
1829 | result = write_pbe_enc_params (pbes2_asn, enc_params); | ||
1830 | if (result < 0) | ||
1831 | { | ||
1832 | gnutls_assert (); | ||
1833 | goto error; | ||
1834 | } | ||
1835 | |||
1836 | result = _gnutls_x509_der_encode_and_copy (pbes2_asn, "", | ||
1837 | pkcs8_asn, where, 0); | ||
1838 | if (result < 0) | ||
1839 | { | ||
1840 | gnutls_assert (); | ||
1841 | goto error; | ||
1842 | } | ||
1843 | |||
1844 | asn1_delete_structure (&pbes2_asn); | ||
1845 | } | ||
1846 | else | ||
1847 | { /* PKCS12 schemas */ | ||
1848 | |||
1849 | if ((result = | ||
1850 | asn1_create_element (_gnutls_get_pkix (), | ||
1851 | "PKIX1.pkcs-12-PbeParams", | ||
1852 | &pbes2_asn)) != ASN1_SUCCESS) | ||
1853 | { | ||
1854 | gnutls_assert (); | ||
1855 | result = _gnutls_asn2err (result); | ||
1856 | goto error; | ||
1857 | } | ||
1858 | |||
1859 | result = write_pkcs12_kdf_params (pbes2_asn, kdf_params); | ||
1860 | if (result < 0) | ||
1861 | { | ||
1862 | gnutls_assert (); | ||
1863 | goto error; | ||
1864 | } | ||
1865 | |||
1866 | result = _gnutls_x509_der_encode_and_copy (pbes2_asn, "", | ||
1867 | pkcs8_asn, where, 0); | ||
1868 | if (result < 0) | ||
1869 | { | ||
1870 | gnutls_assert (); | ||
1871 | goto error; | ||
1872 | } | ||
1873 | |||
1874 | asn1_delete_structure (&pbes2_asn); | ||
1875 | |||
1876 | } | ||
1877 | |||
1878 | return 0; | ||
1879 | |||
1880 | error: | ||
1881 | asn1_delete_structure (&pbes2_asn); | ||
1882 | return result; | ||
1883 | |||
1884 | } | ||
1885 | |||
1886 | static int | ||
1887 | encrypt_data (const gnutls_datum_t * plain, | ||
1888 | const struct pbe_enc_params *enc_params, | ||
1889 | gnutls_datum_t * key, gnutls_datum_t * encrypted) | ||
1890 | { | ||
1891 | int result; | ||
1892 | int data_size; | ||
1893 | opaque *data = NULL; | ||
1894 | gnutls_datum_t d_iv; | ||
1895 | cipher_hd_t ch = NULL; | ||
1896 | opaque pad, pad_size; | ||
1897 | |||
1898 | pad_size = _gnutls_cipher_get_block_size (enc_params->cipher); | ||
1899 | |||
1900 | if (pad_size == 1) /* stream */ | ||
1901 | pad_size = 0; | ||
1902 | |||
1903 | data = gnutls_malloc (plain->size + pad_size); | ||
1904 | if (data == NULL) | ||
1905 | { | ||
1906 | gnutls_assert (); | ||
1907 | return GNUTLS_E_MEMORY_ERROR; | ||
1908 | } | ||
1909 | |||
1910 | memcpy (data, plain->data, plain->size); | ||
1911 | |||
1912 | if (pad_size> 0) | ||
1913 | { | ||
1914 | pad = pad_size - (plain->size % pad_size); | ||
1915 | if (pad == 0) | ||
1916 | pad = pad_size; | ||
1917 | memset (&data[plain->size], pad, pad); | ||
1918 | } | ||
1919 | else | ||
1920 | pad = 0; | ||
1921 | |||
1922 | data_size = plain->size + pad; | ||
1923 | |||
1924 | d_iv.data = (opaque *) enc_params->iv; | ||
1925 | d_iv.size = enc_params->iv_size; | ||
1926 | ch = _gnutls_cipher_init (enc_params->cipher, key, &d_iv); | ||
1927 | |||
1928 | if (ch == GNUTLS_CIPHER_FAILED) | ||
1929 | { | ||
1930 | gnutls_assert (); | ||
1931 | result = GNUTLS_E_ENCRYPTION_FAILED; | ||
1932 | goto error; | ||
1933 | } | ||
1934 | |||
1935 | result = _gnutls_cipher_encrypt (ch, data, data_size); | ||
1936 | if (result < 0) | ||
1937 | { | ||
1938 | gnutls_assert (); | ||
1939 | goto error; | ||
1940 | } | ||
1941 | |||
1942 | encrypted->data = data; | ||
1943 | encrypted->size = data_size; | ||
1944 | |||
1945 | _gnutls_cipher_deinit (ch); | ||
1946 | |||
1947 | return 0; | ||
1948 | |||
1949 | error: | ||
1950 | gnutls_free (data); | ||
1951 | if (ch != NULL) | ||
1952 | _gnutls_cipher_deinit (ch); | ||
1953 | return result; | ||
1954 | } | ||
1955 | |||
1956 | /* Decrypts a PKCS #7 encryptedData. The output is allocated | ||
1957 | * and stored in dec. | ||
1958 | */ | ||
1959 | int | ||
1960 | _gnutls_pkcs7_decrypt_data (const gnutls_datum_t * data, | ||
1961 | const char *password, gnutls_datum_t * dec) | ||
1962 | { | ||
1963 | int result, len; | ||
1964 | char enc_oid[64]; | ||
1965 | gnutls_datum_t tmp; | ||
1966 | ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY, pkcs7_asn = ASN1_TYPE_EMPTY; | ||
1967 | int params_start, params_end, params_len; | ||
1968 | struct pbkdf2_params kdf_params; | ||
1969 | struct pbe_enc_params enc_params; | ||
1970 | schema_id schema; | ||
1971 | |||
1972 | if ((result = | ||
1973 | asn1_create_element (_gnutls_get_pkix (), | ||
1974 | "PKIX1.pkcs-7-EncryptedData", | ||
1975 | &pkcs7_asn)) != ASN1_SUCCESS) | ||
1976 | { | ||
1977 | gnutls_assert (); | ||
1978 | result = _gnutls_asn2err (result); | ||
1979 | goto error; | ||
1980 | } | ||
1981 | |||
1982 | result = asn1_der_decoding (&pkcs7_asn, data->data, data->size, NULL); | ||
1983 | if (result != ASN1_SUCCESS) | ||
1984 | { | ||
1985 | gnutls_assert (); | ||
1986 | result = _gnutls_asn2err (result); | ||
1987 | goto error; | ||
1988 | } | ||
1989 | |||
1990 | /* Check the encryption schema OID | ||
1991 | */ | ||
1992 | len = sizeof (enc_oid); | ||
1993 | result = | ||
1994 | asn1_read_value (pkcs7_asn, | ||
1995 | "encryptedContentInfo.contentEncryptionAlgorithm.algorithm", | ||
1996 | enc_oid, &len); | ||
1997 | if (result != ASN1_SUCCESS) | ||
1998 | { | ||
1999 | gnutls_assert (); | ||
2000 | result = _gnutls_asn2err (result); | ||
2001 | goto error; | ||
2002 | } | ||
2003 | |||
2004 | if ((result = check_schema (enc_oid)) < 0) | ||
2005 | { | ||
2006 | gnutls_assert (); | ||
2007 | goto error; | ||
2008 | } | ||
2009 | schema = result; | ||
2010 | |||
2011 | /* Get the DER encoding of the parameters. | ||
2012 | */ | ||
2013 | result = | ||
2014 | asn1_der_decoding_startEnd (pkcs7_asn, data->data, data->size, | ||
2015 | "encryptedContentInfo.contentEncryptionAlgorithm.parameters", | ||
2016 | ¶ms_start, ¶ms_end); | ||
2017 | if (result != ASN1_SUCCESS) | ||
2018 | { | ||
2019 | gnutls_assert (); | ||
2020 | result = _gnutls_asn2err (result); | ||
2021 | goto error; | ||
2022 | } | ||
2023 | params_len = params_end - params_start + 1; | ||
2024 | |||
2025 | result = | ||
2026 | read_pkcs_schema_params (schema, password, | ||
2027 | &data->data[params_start], | ||
2028 | params_len, &kdf_params, &enc_params); | ||
2029 | if (result < ASN1_SUCCESS) | ||
2030 | { | ||
2031 | gnutls_assert (); | ||
2032 | result = _gnutls_asn2err (result); | ||
2033 | goto error; | ||
2034 | } | ||
2035 | |||
2036 | /* Parameters have been decoded. Now | ||
2037 | * decrypt the EncryptedData. | ||
2038 | */ | ||
2039 | |||
2040 | result = | ||
2041 | decrypt_data (schema, pkcs7_asn, | ||
2042 | "encryptedContentInfo.encryptedContent", password, | ||
2043 | &kdf_params, &enc_params, &tmp); | ||
2044 | if (result < 0) | ||
2045 | { | ||
2046 | gnutls_assert (); | ||
2047 | goto error; | ||
2048 | } | ||
2049 | |||
2050 | asn1_delete_structure (&pkcs7_asn); | ||
2051 | |||
2052 | *dec = tmp; | ||
2053 | |||
2054 | return 0; | ||
2055 | |||
2056 | error: | ||
2057 | asn1_delete_structure (&pbes2_asn); | ||
2058 | asn1_delete_structure (&pkcs7_asn); | ||
2059 | return result; | ||
2060 | } | ||
2061 | |||
2062 | /* Encrypts to a PKCS #7 encryptedData. The output is allocated | ||
2063 | * and stored in enc. | ||
2064 | */ | ||
2065 | int | ||
2066 | _gnutls_pkcs7_encrypt_data (schema_id schema, | ||
2067 | const gnutls_datum_t * data, | ||
2068 | const char *password, gnutls_datum_t * enc) | ||
2069 | { | ||
2070 | int result; | ||
2071 | gnutls_datum_t key = | ||
2072 | { NULL, 0}; | ||
2073 | gnutls_datum_t tmp = | ||
2074 | { NULL, 0}; | ||
2075 | ASN1_TYPE pkcs7_asn = ASN1_TYPE_EMPTY; | ||
2076 | struct pbkdf2_params kdf_params; | ||
2077 | struct pbe_enc_params enc_params; | ||
2078 | |||
2079 | if ((result = | ||
2080 | asn1_create_element (_gnutls_get_pkix (), | ||
2081 | "PKIX1.pkcs-7-EncryptedData", | ||
2082 | &pkcs7_asn)) != ASN1_SUCCESS) | ||
2083 | { | ||
2084 | gnutls_assert (); | ||
2085 | result = _gnutls_asn2err (result); | ||
2086 | goto error; | ||
2087 | } | ||
2088 | |||
2089 | /* Write the encryption schema OID | ||
2090 | */ | ||
2091 | switch (schema) | ||
2092 | { | ||
2093 | case PBES2: | ||
2094 | result = | ||
2095 | asn1_write_value (pkcs7_asn, | ||
2096 | "encryptedContentInfo.contentEncryptionAlgorithm.algorithm", | ||
2097 | PBES2_OID, 1); | ||
2098 | break; | ||
2099 | case PKCS12_3DES_SHA1: | ||
2100 | result = | ||
2101 | asn1_write_value (pkcs7_asn, | ||
2102 | "encryptedContentInfo.contentEncryptionAlgorithm.algorithm", | ||
2103 | PKCS12_PBE_3DES_SHA1_OID, 1); | ||
2104 | break; | ||
2105 | case PKCS12_ARCFOUR_SHA1: | ||
2106 | result = | ||
2107 | asn1_write_value (pkcs7_asn, | ||
2108 | "encryptedContentInfo.contentEncryptionAlgorithm.algorithm", | ||
2109 | PKCS12_PBE_ARCFOUR_SHA1_OID, 1); | ||
2110 | break; | ||
2111 | case PKCS12_RC2_40_SHA1: | ||
2112 | result = | ||
2113 | asn1_write_value (pkcs7_asn, | ||
2114 | "encryptedContentInfo.contentEncryptionAlgorithm.algorithm", | ||
2115 | PKCS12_PBE_RC2_40_SHA1_OID, 1); | ||
2116 | break; | ||
2117 | |||
2118 | } | ||
2119 | |||
2120 | if (result != ASN1_SUCCESS) | ||
2121 | { | ||
2122 | gnutls_assert (); | ||
2123 | result = _gnutls_asn2err (result); | ||
2124 | goto error; | ||
2125 | } | ||
2126 | |||
2127 | /* Generate a symmetric key. | ||
2128 | */ | ||
2129 | |||
2130 | result = generate_key (schema, password, &kdf_params, &enc_params, &key); | ||
2131 | if (result < 0) | ||
2132 | { | ||
2133 | gnutls_assert (); | ||
2134 | goto error; | ||
2135 | } | ||
2136 | |||
2137 | result = write_schema_params (schema, pkcs7_asn, | ||
2138 | "encryptedContentInfo.contentEncryptionAlgorithm.parameters", | ||
2139 | &kdf_params, &enc_params); | ||
2140 | if (result < 0) | ||
2141 | { | ||
2142 | gnutls_assert (); | ||
2143 | goto error; | ||
2144 | } | ||
2145 | |||
2146 | /* Parameters have been encoded. Now | ||
2147 | * encrypt the Data. | ||
2148 | */ | ||
2149 | result = encrypt_data (data, &enc_params, &key, &tmp); | ||
2150 | if (result < 0) | ||
2151 | { | ||
2152 | gnutls_assert (); | ||
2153 | goto error; | ||
2154 | } | ||
2155 | |||
2156 | /* write the encrypted data. | ||
2157 | */ | ||
2158 | result = | ||
2159 | asn1_write_value (pkcs7_asn, | ||
2160 | "encryptedContentInfo.encryptedContent", tmp.data, | ||
2161 | tmp.size); | ||
2162 | if (result != ASN1_SUCCESS) | ||
2163 | { | ||
2164 | gnutls_assert (); | ||
2165 | result = _gnutls_asn2err (result); | ||
2166 | goto error; | ||
2167 | } | ||
2168 | |||
2169 | _gnutls_free_datum (&tmp); | ||
2170 | _gnutls_free_datum (&key); | ||
2171 | |||
2172 | /* Now write the rest of the pkcs-7 stuff. | ||
2173 | */ | ||
2174 | |||
2175 | result = _gnutls_x509_write_uint32 (pkcs7_asn, "version", 0); | ||
2176 | if (result < 0) | ||
2177 | { | ||
2178 | gnutls_assert (); | ||
2179 | goto error; | ||
2180 | } | ||
2181 | |||
2182 | result = | ||
2183 | asn1_write_value (pkcs7_asn, "encryptedContentInfo.contentType", | ||
2184 | DATA_OID, 1); | ||
2185 | if (result != ASN1_SUCCESS) | ||
2186 | { | ||
2187 | gnutls_assert (); | ||
2188 | result = _gnutls_asn2err (result); | ||
2189 | goto error; | ||
2190 | } | ||
2191 | |||
2192 | result = asn1_write_value (pkcs7_asn, "unprotectedAttrs", NULL, 0); | ||
2193 | if (result != ASN1_SUCCESS) | ||
2194 | { | ||
2195 | gnutls_assert (); | ||
2196 | result = _gnutls_asn2err (result); | ||
2197 | goto error; | ||
2198 | } | ||
2199 | |||
2200 | /* Now encode and copy the DER stuff. | ||
2201 | */ | ||
2202 | result = _gnutls_x509_der_encode (pkcs7_asn, "", enc, 0); | ||
2203 | |||
2204 | asn1_delete_structure (&pkcs7_asn); | ||
2205 | |||
2206 | if (result < 0) | ||
2207 | { | ||
2208 | gnutls_assert (); | ||
2209 | goto error; | ||
2210 | } | ||
2211 | |||
2212 | error: | ||
2213 | _gnutls_free_datum (&key); | ||
2214 | _gnutls_free_datum (&tmp); | ||
2215 | asn1_delete_structure (&pkcs7_asn); | ||
2216 | return result; | ||
2217 | } | ||
2218 | |||
2219 | #endif | ||