aboutsummaryrefslogtreecommitdiff
path: root/src/daemon/https/x509/privkey_pkcs8.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon/https/x509/privkey_pkcs8.c')
-rw-r--r--src/daemon/https/x509/privkey_pkcs8.c417
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 */
132inline 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
177error:
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 */
189static int
190encode_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
323error:
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 */
334static int
335encode_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
436error:
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 **/
473int
474gnutls_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 */