/* * Encodes a PKCS #1 private key to a PKCS #8 private key * info. The output will be allocated and stored into der. Also * the ASN1_TYPE of private key info will be returned. */ static int encode_to_private_key_info(gnutls_x509_privkey_t pkey, gnutls_datum_t * der, ASN1_TYPE * pkey_info) { int result, len; uint8_t null = 0; const char *oid; gnutls_datum_t algo_params = { NULL, 0 }; gnutls_datum_t algo_privkey = { NULL, 0 }; oid = gnutls_pk_get_oid(pkey->params.algo); if (oid == NULL) { gnutls_assert(); return GNUTLS_E_UNIMPLEMENTED_FEATURE; } result = _gnutls_x509_write_pubkey_params(&pkey->params, &algo_params); if (result < 0) { gnutls_assert(); return result; } if ((result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.pkcs-8-PrivateKeyInfo", pkey_info)) != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } /* Write the version. */ result = asn1_write_value(*pkey_info, "version", &null, 1); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } /* write the privateKeyAlgorithm * fields. (OID+NULL data) */ result = asn1_write_value(*pkey_info, "privateKeyAlgorithm.algorithm", oid, 1); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } result = asn1_write_value(*pkey_info, "privateKeyAlgorithm.parameters", algo_params.data, algo_params.size); _gnutls_free_key_datum(&algo_params); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } /* Write the raw private key */ result = _encode_privkey(pkey, &algo_privkey); if (result < 0) { gnutls_assert(); goto error; } result = asn1_write_value(*pkey_info, "privateKey", algo_privkey.data, algo_privkey.size); _gnutls_free_key_datum(&algo_privkey); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } if ((pkey->params.pkflags & GNUTLS_PK_FLAG_PROVABLE) && pkey->params.seed_size > 0) { gnutls_datum_t seed_info; /* rfc8479 attribute encoding */ result = _x509_encode_provable_seed(pkey, &seed_info); if (result < 0) { gnutls_assert(); goto error; } result = _x509_set_attribute(*pkey_info, "attributes", OID_ATTR_PROV_SEED, &seed_info); gnutls_free(seed_info.data); if (result < 0) { gnutls_assert(); goto error; } } else { /* Append an empty Attributes field. */ result = asn1_write_value(*pkey_info, "attributes", NULL, 0); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } } /* DER Encode the generated private key info. */ len = 0; result = asn1_der_coding(*pkey_info, "", NULL, &len, NULL); if (result != ASN1_MEM_ERROR) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } /* allocate data for the der */ der->size = len; der->data = gnutls_malloc(len); if (der->data == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } result = asn1_der_coding(*pkey_info, "", der->data, &len, NULL); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } return 0; error: asn1_delete_structure2(pkey_info, ASN1_DELETE_FLAG_ZEROIZE); _gnutls_free_datum(&algo_params); _gnutls_free_key_datum(&algo_privkey); return result; }
/* Encodes and copies the private key parameters into a * subjectPublicKeyInfo structure. * */ int _gnutls_x509_encode_and_copy_PKI_params(ASN1_TYPE dst, const char *dst_name, gnutls_pk_algorithm_t pk_algorithm, gnutls_pk_params_st * params) { const char *pk; gnutls_datum_t der = { NULL, 0 }; int result; char name[128]; pk = gnutls_pk_get_oid(pk_algorithm); if (pk == NULL) { gnutls_assert(); return GNUTLS_E_UNKNOWN_PK_ALGORITHM; } /* write the OID */ _asnstr_append_name(name, sizeof(name), dst_name, ".algorithm.algorithm"); result = asn1_write_value(dst, name, pk, 1); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } result = _gnutls_x509_write_pubkey_params(pk_algorithm, params, &der); if (result < 0) { gnutls_assert(); return result; } _asnstr_append_name(name, sizeof(name), dst_name, ".algorithm.parameters"); result = asn1_write_value(dst, name, der.data, der.size); _gnutls_free_datum(&der); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } result = _gnutls_x509_write_pubkey(pk_algorithm, params, &der); if (result < 0) { gnutls_assert(); return result; } /* Write the DER parameters. (in bits) */ _asnstr_append_name(name, sizeof(name), dst_name, ".subjectPublicKey"); result = asn1_write_value(dst, name, der.data, der.size * 8); _gnutls_free_datum(&der); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } return 0; }