int read_pkcs_schema_params(schema_id schema, const char *password,
			    const opaque * data, int data_size,
			    struct pbkdf2_params *kdf_params,
			    struct pbe_enc_params *enc_params)
{
    ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY;
    int result;
    gnutls_datum_t tmp;

    switch (schema) {

    case PBES2:

	/* Now check the key derivation and the encryption
	 * functions.
	 */
	if ((result =
	     asn1_create_element(_gnutls_get_pkix(),
				 "PKIX1.pkcs-5-PBES2-params",
				 &pbes2_asn)) != ASN1_SUCCESS) {
	    gnutls_assert();
	    result = _gnutls_asn2err(result);
	    goto error;
	}

	/* Decode the parameters.
	 */
	result = asn1_der_decoding(&pbes2_asn, data, data_size, NULL);
	if (result != ASN1_SUCCESS) {
	    gnutls_assert();
	    result = _gnutls_asn2err(result);
	    goto error;
	}

	tmp.data = (opaque *) data;
	tmp.size = data_size;

	result = read_pbkdf2_params(pbes2_asn, &tmp, kdf_params);
	if (result < 0) {
	    gnutls_assert();
	    result = _gnutls_asn2err(result);
	    goto error;
	}

	result = read_pbe_enc_params(pbes2_asn, &tmp, enc_params);
	if (result < 0) {
	    gnutls_assert();
	    result = _gnutls_asn2err(result);
	    goto error;
	}

	asn1_delete_structure(&pbes2_asn);
	return 0;
	break;

    case PKCS12_3DES_SHA1:
    case PKCS12_ARCFOUR_SHA1:
    case PKCS12_RC2_40_SHA1:

	if ((schema) == PKCS12_3DES_SHA1) {
	    enc_params->cipher = GNUTLS_CIPHER_3DES_CBC;
	    enc_params->iv_size = 8;
	} else if ((schema) == PKCS12_ARCFOUR_SHA1) {
	    enc_params->cipher = GNUTLS_CIPHER_ARCFOUR_128;
	    enc_params->iv_size = 0;
	} else if ((schema) == PKCS12_RC2_40_SHA1) {
	    enc_params->cipher = GNUTLS_CIPHER_RC2_40_CBC;
	    enc_params->iv_size = 8;
	}

	if ((result =
	     asn1_create_element(_gnutls_get_pkix(),
				 "PKIX1.pkcs-12-PbeParams",
				 &pbes2_asn)) != ASN1_SUCCESS) {
	    gnutls_assert();
	    result = _gnutls_asn2err(result);
	    goto error;
	}

	/* Decode the parameters.
	 */
	result = asn1_der_decoding(&pbes2_asn, data, data_size, NULL);
	if (result != ASN1_SUCCESS) {
	    gnutls_assert();
	    result = _gnutls_asn2err(result);
	    goto error;
	}

	result = read_pkcs12_kdf_params(pbes2_asn, kdf_params);
	if (result < 0) {
	    gnutls_assert();
	    goto error;
	}

	if (enc_params->iv_size) {
	    result =
		_pkcs12_string_to_key(2 /*IV*/, kdf_params->salt,
				      kdf_params->salt_size,
				      kdf_params->iter_count, password,
				      enc_params->iv_size, enc_params->iv);
	    if (result < 0) {
		gnutls_assert();
		goto error;
	    }

	}

	asn1_delete_structure(&pbes2_asn);

	return 0;
	break;

    }				/* switch */

    return GNUTLS_E_UNKNOWN_CIPHER_TYPE;

  error:
    asn1_delete_structure(&pbes2_asn);
    return result;
}
int read_pkcs_schema_params(schema_id schema, const char *password,
			    const opaque * data, int data_size,
			    struct pbkdf2_params *kdf_params,
			    struct pbe_enc_params *enc_params)
{
    ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY;
    int result;
    gnutls_datum_t tmp;

    switch (schema) {

    case PBES2:

	 
	if ((result =
	     asn1_create_element(_gnutls_get_pkix(),
				 "PKIX1.pkcs-5-PBES2-params",
				 &pbes2_asn)) != ASN1_SUCCESS) {
	    gnutls_assert();
	    result = _gnutls_asn2err(result);
	    goto error;
	}

	 
	result = asn1_der_decoding(&pbes2_asn, data, data_size, NULL);
	if (result != ASN1_SUCCESS) {
	    gnutls_assert();
	    result = _gnutls_asn2err(result);
	    goto error;
	}

	tmp.data = (opaque *) data;
	tmp.size = data_size;

	result = read_pbkdf2_params(pbes2_asn, &tmp, kdf_params);
	if (result < 0) {
	    gnutls_assert();
	    result = _gnutls_asn2err(result);
	    goto error;
	}

	result = read_pbe_enc_params(pbes2_asn, &tmp, enc_params);
	if (result < 0) {
	    gnutls_assert();
	    result = _gnutls_asn2err(result);
	    goto error;
	}

	asn1_delete_structure(&pbes2_asn);
	return 0;
	break;

    case PKCS12_3DES_SHA1:
    case PKCS12_ARCFOUR_SHA1:
    case PKCS12_RC2_40_SHA1:

	if ((schema) == PKCS12_3DES_SHA1) {
	    enc_params->cipher = GNUTLS_CIPHER_3DES_CBC;
	    enc_params->iv_size = 8;
	} else if ((schema) == PKCS12_ARCFOUR_SHA1) {
	    enc_params->cipher = GNUTLS_CIPHER_ARCFOUR_128;
	    enc_params->iv_size = 0;
	} else if ((schema) == PKCS12_RC2_40_SHA1) {
	    enc_params->cipher = GNUTLS_CIPHER_RC2_40_CBC;
	    enc_params->iv_size = 8;
	}

	if ((result =
	     asn1_create_element(_gnutls_get_pkix(),
				 "PKIX1.pkcs-12-PbeParams",
				 &pbes2_asn)) != ASN1_SUCCESS) {
	    gnutls_assert();
	    result = _gnutls_asn2err(result);
	    goto error;
	}

	 
	result = asn1_der_decoding(&pbes2_asn, data, data_size, NULL);
	if (result != ASN1_SUCCESS) {
	    gnutls_assert();
	    result = _gnutls_asn2err(result);
	    goto error;
	}

	result = read_pkcs12_kdf_params(pbes2_asn, kdf_params);
	if (result < 0) {
	    gnutls_assert();
	    goto error;
	}

	if (enc_params->iv_size) {
	    result =
		_pkcs12_string_to_key(2  , kdf_params->salt,
				      kdf_params->salt_size,
				      kdf_params->iter_count, password,
				      enc_params->iv_size, enc_params->iv);
	    if (result < 0) {
		gnutls_assert();
		goto error;
	    }

	}

	asn1_delete_structure(&pbes2_asn);

	return 0;
	break;

    }				 

    return GNUTLS_E_UNKNOWN_CIPHER_TYPE;

  error:
    asn1_delete_structure(&pbes2_asn);
    return result;
}