diff options
Diffstat (limited to 'src/daemon/https/x509/privkey_pkcs8.c')
-rw-r--r-- | src/daemon/https/x509/privkey_pkcs8.c | 417 |
1 files changed, 0 insertions, 417 deletions
diff --git a/src/daemon/https/x509/privkey_pkcs8.c b/src/daemon/https/x509/privkey_pkcs8.c index 8b92f266..ae2c50dd 100644 --- a/src/daemon/https/x509/privkey_pkcs8.c +++ b/src/daemon/https/x509/privkey_pkcs8.c | |||
@@ -125,423 +125,6 @@ check_schema (const char *oid) | |||
125 | return GNUTLS_E_UNKNOWN_CIPHER_TYPE; | 125 | return GNUTLS_E_UNKNOWN_CIPHER_TYPE; |
126 | } | 126 | } |
127 | 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_t pkey, gnutls_datum_t * 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 MHD_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_t algo_params = { NULL, 0 }; | ||
197 | gnutls_datum_t algo_privkey = { NULL, 0 }; | ||
198 | |||
199 | if (pkey->pk_algorithm == MHD_GNUTLS_PK_RSA) | ||
200 | { | ||
201 | oid = PK_PKIX1_RSA_OID; | ||
202 | /* parameters are null | ||
203 | */ | ||
204 | } | ||
205 | else | ||
206 | { | ||
207 | oid = PK_DSA_OID; | ||
208 | result = | ||
209 | _gnutls_x509_write_dsa_params (pkey->params, pkey->params_size, | ||
210 | &algo_params); | ||
211 | if (result < 0) | ||
212 | { | ||
213 | gnutls_assert (); | ||
214 | return result; | ||
215 | } | ||
216 | } | ||
217 | |||
218 | if ((result = | ||
219 | asn1_create_element (_gnutls_get_pkix (), | ||
220 | "PKIX1.pkcs-8-PrivateKeyInfo", | ||
221 | pkey_info)) != ASN1_SUCCESS) | ||
222 | { | ||
223 | gnutls_assert (); | ||
224 | result = mhd_gtls_asn2err (result); | ||
225 | goto error; | ||
226 | } | ||
227 | |||
228 | /* Write the version. | ||
229 | */ | ||
230 | result = asn1_write_value (*pkey_info, "version", &null, 1); | ||
231 | if (result != ASN1_SUCCESS) | ||
232 | { | ||
233 | gnutls_assert (); | ||
234 | result = mhd_gtls_asn2err (result); | ||
235 | goto error; | ||
236 | } | ||
237 | |||
238 | /* write the privateKeyAlgorithm | ||
239 | * fields. (OID+NULL data) | ||
240 | */ | ||
241 | result = | ||
242 | asn1_write_value (*pkey_info, "privateKeyAlgorithm.algorithm", oid, 1); | ||
243 | if (result != ASN1_SUCCESS) | ||
244 | { | ||
245 | gnutls_assert (); | ||
246 | result = mhd_gtls_asn2err (result); | ||
247 | goto error; | ||
248 | } | ||
249 | |||
250 | result = | ||
251 | asn1_write_value (*pkey_info, "privateKeyAlgorithm.parameters", | ||
252 | algo_params.data, algo_params.size); | ||
253 | _gnutls_free_datum (&algo_params); | ||
254 | if (result != ASN1_SUCCESS) | ||
255 | { | ||
256 | gnutls_assert (); | ||
257 | result = mhd_gtls_asn2err (result); | ||
258 | goto error; | ||
259 | } | ||
260 | |||
261 | /* Write the raw private key | ||
262 | */ | ||
263 | result = _encode_privkey (pkey, &algo_privkey); | ||
264 | if (result < 0) | ||
265 | { | ||
266 | gnutls_assert (); | ||
267 | goto error; | ||
268 | } | ||
269 | |||
270 | result = | ||
271 | asn1_write_value (*pkey_info, "privateKey", algo_privkey.data, | ||
272 | algo_privkey.size); | ||
273 | _gnutls_free_datum (&algo_privkey); | ||
274 | |||
275 | if (result != ASN1_SUCCESS) | ||
276 | { | ||
277 | gnutls_assert (); | ||
278 | result = mhd_gtls_asn2err (result); | ||
279 | goto error; | ||
280 | } | ||
281 | |||
282 | /* Append an empty Attributes field. | ||
283 | */ | ||
284 | result = asn1_write_value (*pkey_info, "attributes", NULL, 0); | ||
285 | if (result != ASN1_SUCCESS) | ||
286 | { | ||
287 | gnutls_assert (); | ||
288 | result = mhd_gtls_asn2err (result); | ||
289 | goto error; | ||
290 | } | ||
291 | |||
292 | /* DER Encode the generated private key info. | ||
293 | */ | ||
294 | len = 0; | ||
295 | result = asn1_der_coding (*pkey_info, "", NULL, &len, NULL); | ||
296 | if (result != ASN1_MEM_ERROR) | ||
297 | { | ||
298 | gnutls_assert (); | ||
299 | result = mhd_gtls_asn2err (result); | ||
300 | goto error; | ||
301 | } | ||
302 | |||
303 | /* allocate data for the der | ||
304 | */ | ||
305 | der->size = len; | ||
306 | der->data = gnutls_malloc (len); | ||
307 | if (der->data == NULL) | ||
308 | { | ||
309 | gnutls_assert (); | ||
310 | return GNUTLS_E_MEMORY_ERROR; | ||
311 | } | ||
312 | |||
313 | result = asn1_der_coding (*pkey_info, "", der->data, &len, NULL); | ||
314 | if (result != ASN1_SUCCESS) | ||
315 | { | ||
316 | gnutls_assert (); | ||
317 | result = mhd_gtls_asn2err (result); | ||
318 | goto error; | ||
319 | } | ||
320 | |||
321 | return 0; | ||
322 | |||
323 | error: | ||
324 | asn1_delete_structure (pkey_info); | ||
325 | _gnutls_free_datum (&algo_params); | ||
326 | _gnutls_free_datum (&algo_privkey); | ||
327 | return result; | ||
328 | |||
329 | } | ||
330 | |||
331 | /* Converts a PKCS #8 private key info to | ||
332 | * a PKCS #8 EncryptedPrivateKeyInfo. | ||
333 | */ | ||
334 | static int | ||
335 | encode_to_pkcs8_key (schema_id schema, const gnutls_datum_t * der_key, | ||
336 | const char *password, ASN1_TYPE * out) | ||
337 | { | ||
338 | int result; | ||
339 | gnutls_datum_t key = { NULL, 0 }; | ||
340 | gnutls_datum_t tmp = { NULL, 0 }; | ||
341 | ASN1_TYPE pkcs8_asn = ASN1_TYPE_EMPTY; | ||
342 | struct pbkdf2_params kdf_params; | ||
343 | struct pbe_enc_params enc_params; | ||
344 | |||
345 | if ((result = | ||
346 | asn1_create_element (_gnutls_get_pkix (), | ||
347 | "PKIX1.pkcs-8-EncryptedPrivateKeyInfo", | ||
348 | &pkcs8_asn)) != ASN1_SUCCESS) | ||
349 | { | ||
350 | gnutls_assert (); | ||
351 | result = mhd_gtls_asn2err (result); | ||
352 | goto error; | ||
353 | } | ||
354 | |||
355 | /* Write the encryption schema OID | ||
356 | */ | ||
357 | switch (schema) | ||
358 | { | ||
359 | case PBES2: | ||
360 | result = | ||
361 | asn1_write_value (pkcs8_asn, "encryptionAlgorithm.algorithm", | ||
362 | PBES2_OID, 1); | ||
363 | break; | ||
364 | case PKCS12_3DES_SHA1: | ||
365 | result = | ||
366 | asn1_write_value (pkcs8_asn, "encryptionAlgorithm.algorithm", | ||
367 | PKCS12_PBE_3DES_SHA1_OID, 1); | ||
368 | break; | ||
369 | case PKCS12_ARCFOUR_SHA1: | ||
370 | result = | ||
371 | asn1_write_value (pkcs8_asn, "encryptionAlgorithm.algorithm", | ||
372 | PKCS12_PBE_ARCFOUR_SHA1_OID, 1); | ||
373 | break; | ||
374 | case PKCS12_RC2_40_SHA1: | ||
375 | result = | ||
376 | asn1_write_value (pkcs8_asn, "encryptionAlgorithm.algorithm", | ||
377 | PKCS12_PBE_RC2_40_SHA1_OID, 1); | ||
378 | break; | ||
379 | |||
380 | } | ||
381 | |||
382 | if (result != ASN1_SUCCESS) | ||
383 | { | ||
384 | gnutls_assert (); | ||
385 | result = mhd_gtls_asn2err (result); | ||
386 | goto error; | ||
387 | } | ||
388 | |||
389 | /* Generate a symmetric key. | ||
390 | */ | ||
391 | |||
392 | result = generate_key (schema, password, &kdf_params, &enc_params, &key); | ||
393 | if (result < 0) | ||
394 | { | ||
395 | gnutls_assert (); | ||
396 | goto error; | ||
397 | } | ||
398 | |||
399 | result = | ||
400 | write_schema_params (schema, pkcs8_asn, | ||
401 | "encryptionAlgorithm.parameters", &kdf_params, | ||
402 | &enc_params); | ||
403 | if (result < 0) | ||
404 | { | ||
405 | gnutls_assert (); | ||
406 | goto error; | ||
407 | } | ||
408 | |||
409 | /* Parameters have been encoded. Now | ||
410 | * encrypt the Data. | ||
411 | */ | ||
412 | result = encrypt_data (der_key, &enc_params, &key, &tmp); | ||
413 | if (result < 0) | ||
414 | { | ||
415 | gnutls_assert (); | ||
416 | goto error; | ||
417 | } | ||
418 | |||
419 | /* write the encrypted data. | ||
420 | */ | ||
421 | result = asn1_write_value (pkcs8_asn, "encryptedData", tmp.data, tmp.size); | ||
422 | if (result != ASN1_SUCCESS) | ||
423 | { | ||
424 | gnutls_assert (); | ||
425 | result = mhd_gtls_asn2err (result); | ||
426 | goto error; | ||
427 | } | ||
428 | |||
429 | _gnutls_free_datum (&tmp); | ||
430 | _gnutls_free_datum (&key); | ||
431 | |||
432 | *out = pkcs8_asn; | ||
433 | |||
434 | return 0; | ||
435 | |||
436 | error: | ||
437 | _gnutls_free_datum (&key); | ||
438 | _gnutls_free_datum (&tmp); | ||
439 | asn1_delete_structure (&pkcs8_asn); | ||
440 | return result; | ||
441 | } | ||
442 | |||
443 | /** | ||
444 | * gnutls_x509_privkey_export_pkcs8 - This function will export the private key to PKCS8 format | ||
445 | * @key: Holds the key | ||
446 | * @format: the format of output params. One of PEM or DER. | ||
447 | * @password: the password that will be used to encrypt the key. | ||
448 | * @flags: an ORed sequence of gnutls_pkcs_encrypt_flags_t | ||
449 | * @output_data: will contain a private key PEM or DER encoded | ||
450 | * @output_data_size: holds the size of output_data (and will be | ||
451 | * replaced by the actual size of parameters) | ||
452 | * | ||
453 | * This function will export the private key to a PKCS8 structure. | ||
454 | * Both RSA and DSA keys can be exported. For DSA keys we use | ||
455 | * PKCS #11 definitions. If the flags do not specify the encryption | ||
456 | * cipher, then the default 3DES (PBES2) will be used. | ||
457 | * | ||
458 | * The @password can be either ASCII or UTF-8 in the default PBES2 | ||
459 | * encryption schemas, or ASCII for the PKCS12 schemas. | ||
460 | * | ||
461 | * If the buffer provided is not long enough to hold the output, then | ||
462 | * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will | ||
463 | * be returned. | ||
464 | * | ||
465 | * If the structure is PEM encoded, it will have a header | ||
466 | * of "BEGIN ENCRYPTED PRIVATE KEY" or "BEGIN PRIVATE KEY" if | ||
467 | * encryption is not used. | ||
468 | * | ||
469 | * Return value: In case of failure a negative value will be | ||
470 | * returned, and 0 on success. | ||
471 | * | ||
472 | **/ | ||
473 | int | ||
474 | gnutls_x509_privkey_export_pkcs8 (gnutls_x509_privkey_t key, | ||
475 | gnutls_x509_crt_fmt_t format, | ||
476 | const char *password, | ||
477 | unsigned int flags, | ||
478 | void *output_data, | ||
479 | size_t * output_data_size) | ||
480 | { | ||
481 | ASN1_TYPE pkcs8_asn, pkey_info; | ||
482 | int ret; | ||
483 | gnutls_datum_t tmp; | ||
484 | schema_id schema; | ||
485 | |||
486 | if (key == NULL) | ||
487 | { | ||
488 | gnutls_assert (); | ||
489 | return GNUTLS_E_INVALID_REQUEST; | ||
490 | } | ||
491 | |||
492 | /* Get the private key info | ||
493 | * tmp holds the DER encoding. | ||
494 | */ | ||
495 | ret = encode_to_private_key_info (key, &tmp, &pkey_info); | ||
496 | if (ret < 0) | ||
497 | { | ||
498 | gnutls_assert (); | ||
499 | return ret; | ||
500 | } | ||
501 | |||
502 | if (flags & GNUTLS_PKCS_USE_PKCS12_3DES) | ||
503 | schema = PKCS12_3DES_SHA1; | ||
504 | else if (flags & GNUTLS_PKCS_USE_PKCS12_ARCFOUR) | ||
505 | schema = PKCS12_ARCFOUR_SHA1; | ||
506 | else if (flags & GNUTLS_PKCS_USE_PKCS12_RC2_40) | ||
507 | schema = PKCS12_RC2_40_SHA1; | ||
508 | else | ||
509 | schema = PBES2; | ||
510 | |||
511 | if ((flags & GNUTLS_PKCS_PLAIN) || password == NULL) | ||
512 | { | ||
513 | _gnutls_free_datum (&tmp); | ||
514 | |||
515 | ret = | ||
516 | _gnutls_x509_export_int (pkey_info, format, | ||
517 | PEM_UNENCRYPTED_PKCS8, | ||
518 | output_data, output_data_size); | ||
519 | |||
520 | asn1_delete_structure (&pkey_info); | ||
521 | } | ||
522 | else | ||
523 | { | ||
524 | asn1_delete_structure (&pkey_info); /* we don't need it */ | ||
525 | |||
526 | ret = encode_to_pkcs8_key (schema, &tmp, password, &pkcs8_asn); | ||
527 | _gnutls_free_datum (&tmp); | ||
528 | |||
529 | if (ret < 0) | ||
530 | { | ||
531 | gnutls_assert (); | ||
532 | return ret; | ||
533 | } | ||
534 | |||
535 | ret = | ||
536 | _gnutls_x509_export_int (pkcs8_asn, format, PEM_PKCS8, | ||
537 | output_data, output_data_size); | ||
538 | |||
539 | asn1_delete_structure (&pkcs8_asn); | ||
540 | } | ||
541 | |||
542 | return ret; | ||
543 | } | ||
544 | |||
545 | /* Read the parameters cipher, IV, salt etc using the given | 128 | /* Read the parameters cipher, IV, salt etc using the given |
546 | * schema ID. | 129 | * schema ID. |
547 | */ | 130 | */ |