Ejemplo n.º 1
0
/**
 * gnutls_x509_privkey_export2_pkcs8:
 * @key: Holds the key
 * @format: the format of output params. One of PEM or DER.
 * @password: the password that will be used to encrypt the key.
 * @flags: an ORed sequence of gnutls_pkcs_encrypt_flags_t
 * @out: will contain a private key PEM or DER encoded
 *
 * This function will export the private key to a PKCS8 structure.
 * Both RSA and DSA keys can be exported. For DSA keys we use
 * PKCS #11 definitions. If the flags do not specify the encryption
 * cipher, then the default 3DES (PBES2) will be used.
 *
 * The @password can be either ASCII or UTF-8 in the default PBES2
 * encryption schemas, or ASCII for the PKCS12 schemas.
 *
 * The output buffer is allocated using gnutls_malloc().
 *
 * If the structure is PEM encoded, it will have a header
 * of "BEGIN ENCRYPTED PRIVATE KEY" or "BEGIN PRIVATE KEY" if
 * encryption is not used.
 *
 * Returns: In case of failure a negative error code will be
 *   returned, and 0 on success.
 *
 * Since 3.1.3
 **/
int
gnutls_x509_privkey_export2_pkcs8(gnutls_x509_privkey_t key,
				  gnutls_x509_crt_fmt_t format,
				  const char *password,
				  unsigned int flags, gnutls_datum_t * out)
{
	ASN1_TYPE pkcs8_asn = NULL, pkey_info;
	int ret;
	gnutls_datum_t tmp = {NULL, 0};
	schema_id schema;

	if (key == NULL) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	/* Get the private key info
	 * tmp holds the DER encoding.
	 */
	ret = encode_to_private_key_info(key, &tmp, &pkey_info);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	schema = _gnutls_pkcs_flags_to_schema(flags);

	if (((flags & GNUTLS_PKCS_PLAIN) || password == NULL)
	    && !(flags & GNUTLS_PKCS_NULL_PASSWORD)) {
		_gnutls_free_key_datum(&tmp);

		ret =
		    _gnutls_x509_export_int2(pkey_info, format,
					     PEM_UNENCRYPTED_PKCS8, out);

		asn1_delete_structure2(&pkey_info, ASN1_DELETE_FLAG_ZEROIZE);
	} else {
		asn1_delete_structure2(&pkey_info, ASN1_DELETE_FLAG_ZEROIZE);	/* we don't need it */

		ret =
		    encode_to_pkcs8_key(schema, &tmp, password,
					&pkcs8_asn);
		_gnutls_free_key_datum(&tmp);

		if (ret < 0) {
			gnutls_assert();
			return ret;
		}

		ret =
		    _gnutls_x509_export_int2(pkcs8_asn, format, PEM_PKCS8,
					     out);

		asn1_delete_structure2(&pkcs8_asn, ASN1_DELETE_FLAG_ZEROIZE);
	}

	return ret;
}
Ejemplo n.º 2
0
/* Decodes an RSA privateKey from a PKCS8 structure.
 */
static int
_decode_pkcs8_rsa_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey)
{
	int ret;
	gnutls_datum_t tmp = {NULL, 0};

	ret = _gnutls_x509_read_value(pkcs8_asn, "privateKey", &tmp);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	pkey->key = _gnutls_privkey_decode_pkcs1_rsa_key(&tmp, pkey);
	_gnutls_free_key_datum(&tmp);

	if (pkey->key == NULL) {
		ret = GNUTLS_E_PK_INVALID_PRIVKEY;
		gnutls_assert();
		goto error;
	}

	ret = 0;

      error:
	return ret;
}
Ejemplo n.º 3
0
/* Decodes an ECC privateKey from a PKCS8 structure.
 */
static int
_decode_pkcs8_ecc_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey)
{
	int ret;
	gnutls_datum_t tmp = {NULL, 0};
	unsigned char oid[MAX_OID_SIZE];
	unsigned curve = GNUTLS_ECC_CURVE_INVALID;
	int len, result;

	/* openssl PKCS #8 files with ECC keys place the curve in
	 * privateKeyAlgorithm.parameters instead of the ECPrivateKey.parameters.
	 */
	len = sizeof(oid);
	result =
	    asn1_read_value(pkcs8_asn, "privateKeyAlgorithm.parameters",
			    oid, &len);
	if (result == ASN1_SUCCESS) {
		ret = _gnutls_x509_read_ecc_params(oid, len, &curve);
		if (ret < 0) {
			_gnutls_debug_log("PKCS#8: unknown curve OID %s\n", oid);
			curve = GNUTLS_ECC_CURVE_INVALID;
		}
	}

	ret = _gnutls_x509_read_value(pkcs8_asn, "privateKey", &tmp);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret = _gnutls_privkey_decode_ecc_key(&pkey->key, &tmp, pkey, curve);
	_gnutls_free_key_datum(&tmp);

	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret = 0;

      error:
	return ret;
}
Ejemplo n.º 4
0
/* Free all the entry parameters, except if g and n are
 * the static ones defined in gnutls.h
 */
void _gnutls_srp_entry_free(SRP_PWD_ENTRY * entry)
{
	_gnutls_free_key_datum(&entry->v);
	_gnutls_free_datum(&entry->salt);

	if ((entry->g.data != gnutls_srp_1024_group_generator.data)
	    && (entry->g.data != gnutls_srp_3072_group_generator.data))
		_gnutls_free_datum(&entry->g);

	if (entry->n.data != gnutls_srp_1024_group_prime.data &&
	    entry->n.data != gnutls_srp_1536_group_prime.data &&
	    entry->n.data != gnutls_srp_2048_group_prime.data &&
	    entry->n.data != gnutls_srp_3072_group_prime.data &&
	    entry->n.data != gnutls_srp_4096_group_prime.data)
		_gnutls_free_datum(&entry->n);

	gnutls_free(entry->username);
	gnutls_free(entry);
}
Ejemplo n.º 5
0
/* Decodes an RSA-PSS privateKey from a PKCS8 structure.
 */
static int
_decode_pkcs8_rsa_pss_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey)
{
	int ret;
	gnutls_datum_t tmp = {NULL, 0};
	gnutls_x509_spki_st params;

	memset(&params, 0, sizeof(params));

	ret = _gnutls_x509_read_value(pkcs8_asn,
				      "privateKeyAlgorithm.parameters", &tmp);
	if (ret < 0) {
		if (ret == GNUTLS_E_ASN1_VALUE_NOT_FOUND || ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
			goto skip_params;

		gnutls_assert();
		goto error;
	}

	ret = _gnutls_x509_read_rsa_pss_params(tmp.data, tmp.size, &params);
	_gnutls_free_key_datum(&tmp);

	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

 skip_params:
	ret = _decode_pkcs8_rsa_key(pkcs8_asn, pkey);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	pkey->params.algo = GNUTLS_PK_RSA_PSS;
	memcpy(&pkey->params.spki, &params, sizeof(gnutls_x509_spki_st));

	ret = 0;

      error:
	return ret;
}
Ejemplo n.º 6
0
/*
  Process the client key exchange message
*/
static int
_gnutls_proc_rsa_psk_client_kx(gnutls_session_t session, uint8_t * data,
			       size_t _data_size)
{
	gnutls_datum_t username;
	psk_auth_info_t info;
	gnutls_datum_t plaintext;
	gnutls_datum_t ciphertext;
	gnutls_datum_t pwd_psk = { NULL, 0 };
	int ret, dsize;
	int randomize_key = 0;
	ssize_t data_size = _data_size;
	gnutls_psk_server_credentials_t cred;
	gnutls_datum_t premaster_secret = { NULL, 0 };

	cred = (gnutls_psk_server_credentials_t)
	    _gnutls_get_cred(session, GNUTLS_CRD_PSK);

	if (cred == NULL) {
		gnutls_assert();
		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
	}

	ret = _gnutls_auth_info_init(session, GNUTLS_CRD_PSK,
				    sizeof(psk_auth_info_st), 1);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

  /*** 1. Extract user psk_identity ***/

	DECR_LEN(data_size, 2);
	username.size = _gnutls_read_uint16(&data[0]);

	DECR_LEN(data_size, username.size);

	username.data = &data[2];

	/* copy the username to the auth info structures
	 */
	info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
	if (info == NULL) {
		gnutls_assert();
		return GNUTLS_E_INTERNAL_ERROR;
	}

	if (username.size > MAX_USERNAME_SIZE) {
		gnutls_assert();
		return GNUTLS_E_ILLEGAL_SRP_USERNAME;
	}

	memcpy(info->username, username.data, username.size);
	info->username[username.size] = 0;

	/* Adjust data so it points to EncryptedPreMasterSecret */
	data += username.size + 2;

  /*** 2. Decrypt and extract EncryptedPreMasterSecret ***/

	DECR_LEN(data_size, 2);
	ciphertext.data = &data[2];
	dsize = _gnutls_read_uint16(data);

	if (dsize != data_size) {
		gnutls_assert();
		return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
	}
	ciphertext.size = dsize;

	ret =
	    gnutls_privkey_decrypt_data(session->internals.selected_key, 0,
					&ciphertext, &plaintext);
	if (ret < 0 || plaintext.size != GNUTLS_MASTER_SIZE) {
		/* In case decryption fails then don't inform
		 * the peer. Just use a random key. (in order to avoid
		 * attack against pkcs-1 formatting).
		 */
		gnutls_assert();
		_gnutls_debug_log
		    ("auth_rsa_psk: Possible PKCS #1 format attack\n");
		if (ret >= 0) {
			gnutls_free(plaintext.data);
		}
		randomize_key = 1;
	} else {
		/* If the secret was properly formatted, then
		 * check the version number.
		 */
		if (_gnutls_get_adv_version_major(session) !=
		    plaintext.data[0]
		    || (session->internals.allow_wrong_pms == 0
			&& _gnutls_get_adv_version_minor(session) !=
			plaintext.data[1])) {
			/* No error is returned here, if the version number check
			 * fails. We proceed normally.
			 * That is to defend against the attack described in the paper
			 * "Attacking RSA-based sessions in SSL/TLS" by Vlastimil Klima,
			 * Ondej Pokorny and Tomas Rosa.
			 */
			gnutls_assert();
			_gnutls_debug_log
			    ("auth_rsa: Possible PKCS #1 version check format attack\n");
		}
	}


	if (randomize_key != 0) {
		premaster_secret.size = GNUTLS_MASTER_SIZE;
		premaster_secret.data =
		    gnutls_malloc(premaster_secret.size);
		if (premaster_secret.data == NULL) {
			gnutls_assert();
			return GNUTLS_E_MEMORY_ERROR;
		}

		/* we do not need strong random numbers here.
		 */
		ret = gnutls_rnd(GNUTLS_RND_NONCE, premaster_secret.data,
				  premaster_secret.size);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
	} else {
		premaster_secret.data = plaintext.data;
		premaster_secret.size = plaintext.size;
	}

	/* This is here to avoid the version check attack
	 * discussed above.
	 */

	premaster_secret.data[0] = _gnutls_get_adv_version_major(session);
	premaster_secret.data[1] = _gnutls_get_adv_version_minor(session);

	/* find the key of this username
	 */
	ret =
	    _gnutls_psk_pwd_find_entry(session, info->username, &pwd_psk);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret =
	    set_rsa_psk_session_key(session, &pwd_psk, &premaster_secret);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = 0;
      cleanup:
	_gnutls_free_key_datum(&pwd_psk);
	_gnutls_free_temp_key_datum(&premaster_secret);

	return ret;
}
Ejemplo n.º 7
0
static int pkcs8_key_decrypt(const gnutls_datum_t * raw_key,
			     ASN1_TYPE pkcs8_asn, const char *password,
			     gnutls_x509_privkey_t pkey)
{
	int result, len;
	char enc_oid[MAX_OID_SIZE];
	gnutls_datum_t tmp = {NULL, 0};
	int params_start, params_end, params_len;
	struct pbkdf2_params kdf_params;
	struct pbe_enc_params enc_params;
	schema_id schema;

	/* Check the encryption schema OID
	 */
	len = sizeof(enc_oid);
	result =
	    asn1_read_value(pkcs8_asn, "encryptionAlgorithm.algorithm",
			    enc_oid, &len);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		goto error;
	}

	if ((result = _gnutls_check_pkcs_cipher_schema(enc_oid)) < 0) {
		gnutls_assert();
		goto error;
	}

	schema = result;

	/* Get the DER encoding of the parameters.
	 */
	result =
	    asn1_der_decoding_startEnd(pkcs8_asn, raw_key->data,
				       raw_key->size,
				       "encryptionAlgorithm.parameters",
				       &params_start, &params_end);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto error;
	}
	params_len = params_end - params_start + 1;

	result =
	    _gnutls_read_pkcs_schema_params(&schema, password,
				    &raw_key->data[params_start],
				    params_len, &kdf_params, &enc_params);

	if (result < 0) {
		gnutls_assert();
		goto error;
	}

	/* Parameters have been decoded. Now
	 * decrypt the EncryptedData.
	 */
	result =
	    _gnutls_pkcs_raw_decrypt_data(schema, pkcs8_asn, "encryptedData", password,
			 &kdf_params, &enc_params, &tmp);
	if (result < 0) {
		gnutls_assert();
		result = GNUTLS_E_DECRYPTION_FAILED;
		goto error;
	}

	result = decode_private_key_info(&tmp, pkey);
	_gnutls_free_key_datum(&tmp);

	CHECK_ERR_FOR_ENCRYPTED(result);
	if (result < 0) {
		gnutls_assert();
		goto error;
	}

	return 0;

      error:
	return result;
}
Ejemplo n.º 8
0
/* Converts a PKCS #8 private key info to
 * a PKCS #8 EncryptedPrivateKeyInfo.
 */
static int
encode_to_pkcs8_key(schema_id schema, const gnutls_datum_t * der_key,
		    const char *password, ASN1_TYPE * out)
{
	int result;
	gnutls_datum_t key = { NULL, 0 };
	gnutls_datum_t tmp = { NULL, 0 };
	ASN1_TYPE pkcs8_asn = ASN1_TYPE_EMPTY;
	struct pbkdf2_params kdf_params;
	struct pbe_enc_params enc_params;
	const struct pkcs_cipher_schema_st *s;

	s = _gnutls_pkcs_schema_get(schema);
	if (s == NULL || s->decrypt_only) {
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
	}

	if ((result =
	     asn1_create_element(_gnutls_get_pkix(),
				 "PKIX1.pkcs-8-EncryptedPrivateKeyInfo",
				 &pkcs8_asn)) != ASN1_SUCCESS) {
		gnutls_assert();
		return _gnutls_asn2err(result);
	}

	/* Write the encryption schema OID
	 */
	result =
	    asn1_write_value(pkcs8_asn, "encryptionAlgorithm.algorithm",
			     s->write_oid, 1);

	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto error;
	}

	/* Generate a symmetric key.
	 */

	result =
	    _gnutls_pkcs_generate_key(schema, password, &kdf_params, &enc_params, &key);
	if (result < 0) {
		gnutls_assert();
		goto error;
	}

	result =
	    _gnutls_pkcs_write_schema_params(schema, pkcs8_asn,
				"encryptionAlgorithm.parameters",
				&kdf_params, &enc_params);
	if (result < 0) {
		gnutls_assert();
		goto error;
	}

	/* Parameters have been encoded. Now
	 * encrypt the Data.
	 */
	result = _gnutls_pkcs_raw_encrypt_data(der_key, &enc_params, &key, &tmp);
	if (result < 0) {
		gnutls_assert();
		goto error;
	}

	/* write the encrypted data.
	 */
	result =
	    asn1_write_value(pkcs8_asn, "encryptedData", tmp.data,
			     tmp.size);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto error;
	}

	_gnutls_free_datum(&tmp);
	_gnutls_free_key_datum(&key);

	*out = pkcs8_asn;

	return 0;

      error:
	_gnutls_free_key_datum(&key);
	_gnutls_free_datum(&tmp);
	asn1_delete_structure2(&pkcs8_asn, ASN1_DELETE_FLAG_ZEROIZE);
	return result;
}
Ejemplo n.º 9
0
/* 
 * 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;

}
Ejemplo n.º 10
0
/* Decodes an DSA privateKey and params from a PKCS8 structure.
 */
static int
_decode_pkcs8_dsa_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey)
{
	int ret;
	gnutls_datum_t tmp = {NULL, 0};

	gnutls_pk_params_init(&pkey->params);

	ret = _gnutls_x509_read_value(pkcs8_asn, "privateKey", &tmp);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret =
	    _gnutls_x509_read_der_int(tmp.data, tmp.size,
				      &pkey->params.params[4]);
	_gnutls_free_key_datum(&tmp);

	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret =
	    _gnutls_x509_read_value(pkcs8_asn,
				    "privateKeyAlgorithm.parameters",
				    &tmp);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret =
	    _gnutls_x509_read_pubkey_params(GNUTLS_PK_DSA, tmp.data,
					    tmp.size, &pkey->params);
	_gnutls_free_datum(&tmp);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	if (_gnutls_mpi_cmp_ui(pkey->params.params[0], 0) == 0) {
		gnutls_assert();
		ret = GNUTLS_E_ILLEGAL_PARAMETER;
		goto error;
	}

	/* the public key can be generated as g^x mod p */
	ret = _gnutls_mpi_init(&pkey->params.params[3]);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret = _gnutls_mpi_powm(pkey->params.params[3], pkey->params.params[2],
			 pkey->params.params[4], pkey->params.params[0]);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	pkey->params.algo = GNUTLS_PK_DSA;
	pkey->params.params_nr = DSA_PRIVATE_PARAMS;

	ret =
	    _gnutls_asn1_encode_privkey(&pkey->key,
					&pkey->params);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	return 0;

 error:
	if (pkey->params.params_nr != DSA_PRIVATE_PARAMS)
		_gnutls_mpi_release(&pkey->params.params[4]);
	return ret;
}
Ejemplo n.º 11
0
/* Decodes a GOST privateKey from a PKCS8 structure.
 */
static int
_decode_pkcs8_gost_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey,
		       gnutls_pk_algorithm_t algo)
{
	int ret;
	gnutls_datum_t tmp;
	unsigned char oid[3 * MAX_OID_SIZE]; /* GOST parameters can have 3 OIDs at most */
	int len, result;

	gnutls_pk_params_init(&pkey->params);

	len = sizeof(oid);
	result = asn1_read_value(pkcs8_asn, "privateKeyAlgorithm.parameters",
				 oid, &len);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		ret = GNUTLS_E_PARSING_ERROR;
		goto error;
	} else {
		ret = _gnutls_x509_read_gost_params(oid, len, &pkey->params, algo);
		if (ret < 0) {
			gnutls_assert();
			goto error;
		}
	}

	/* Will be fixed later by pk_fixup */
	ret = _gnutls_mpi_init(&pkey->params.params[GOST_X]);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}
	pkey->params.params_nr++;

	ret = _gnutls_mpi_init(&pkey->params.params[GOST_Y]);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}
	pkey->params.params_nr++;

	_gnutls_mpi_set_ui(pkey->params.params[GOST_X], 0);
	_gnutls_mpi_set_ui(pkey->params.params[GOST_Y], 0);

	ret = _gnutls_x509_read_value(pkcs8_asn, "privateKey", &tmp);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret = _privkey_decode_gost_key(&tmp, pkey);
	_gnutls_free_key_datum(&tmp);

	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	pkey->params.algo = algo;

	return 0;

error:
	gnutls_pk_params_clear(&pkey->params);
	gnutls_pk_params_release(&pkey->params);

	return ret;
}
Ejemplo n.º 12
0
/**
 * gnutls_x509_privkey_import_openssl:
 * @key: The structure to store the parsed key
 * @data: The DER or PEM encoded key.
 * @password: the password to decrypt the key (if it is encrypted).
 *
 * This function will convert the given PEM encrypted to 
 * the native gnutls_x509_privkey_t format. The
 * output will be stored in @key.  
 *
 * The @password should be in ASCII. If the password is not provided
 * or wrong then %GNUTLS_E_DECRYPTION_FAILED will be returned.
 *
 * If the Certificate is PEM encoded it should have a header of
 * "PRIVATE KEY" and the "DEK-Info" header. 
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_x509_privkey_import_openssl(gnutls_x509_privkey_t key,
				   const gnutls_datum_t * data,
				   const char *password)
{
	gnutls_cipher_hd_t handle;
	gnutls_cipher_algorithm_t cipher = GNUTLS_CIPHER_UNKNOWN;
	gnutls_datum_t b64_data;
	gnutls_datum_t salt, enc_key;
	unsigned char *key_data;
	size_t key_data_size;
	const char *pem_header = (void *) data->data;
	const char *pem_header_start = (void *) data->data;
	ssize_t pem_header_size;
	int ret;
	unsigned int i, iv_size, l;

	pem_header_size = data->size;

	pem_header =
	    memmem(pem_header, pem_header_size, "PRIVATE KEY---", 14);
	if (pem_header == NULL) {
		gnutls_assert();
		return GNUTLS_E_PARSING_ERROR;
	}

	pem_header_size -= (ptrdiff_t) (pem_header - pem_header_start);

	pem_header = memmem(pem_header, pem_header_size, "DEK-Info: ", 10);
	if (pem_header == NULL) {
		gnutls_assert();
		return GNUTLS_E_PARSING_ERROR;
	}

	pem_header_size =
	    data->size - (ptrdiff_t) (pem_header - pem_header_start) - 10;
	pem_header += 10;

	for (i = 0; i < sizeof(pem_ciphers) / sizeof(pem_ciphers[0]); i++) {
		l = strlen(pem_ciphers[i].name);
		if (!strncmp(pem_header, pem_ciphers[i].name, l) &&
		    pem_header[l] == ',') {
			pem_header += l + 1;
			cipher = pem_ciphers[i].cipher;
			break;
		}
	}

	if (cipher == GNUTLS_CIPHER_UNKNOWN) {
		_gnutls_debug_log
		    ("Unsupported PEM encryption type: %.10s\n",
		     pem_header);
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	iv_size = gnutls_cipher_get_iv_size(cipher);
	salt.size = iv_size;
	salt.data = gnutls_malloc(salt.size);
	if (!salt.data)
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

	for (i = 0; i < salt.size * 2; i++) {
		unsigned char x;
		const char *c = &pem_header[i];

		if (*c >= '0' && *c <= '9')
			x = (*c) - '0';
		else if (*c >= 'A' && *c <= 'F')
			x = (*c) - 'A' + 10;
		else {
			gnutls_assert();
			/* Invalid salt in encrypted PEM file */
			ret = GNUTLS_E_INVALID_REQUEST;
			goto out_salt;
		}
		if (i & 1)
			salt.data[i / 2] |= x;
		else
			salt.data[i / 2] = x << 4;
	}

	pem_header += salt.size * 2;
	if (*pem_header != '\r' && *pem_header != '\n') {
		gnutls_assert();
		ret = GNUTLS_E_INVALID_REQUEST;
		goto out_salt;
	}
	while (*pem_header == '\n' || *pem_header == '\r')
		pem_header++;

	ret =
	    _gnutls_base64_decode((const void *) pem_header,
				  pem_header_size, &b64_data);
	if (ret < 0) {
		gnutls_assert();
		goto out_salt;
	}

	if (b64_data.size < 16) {
		/* Just to be sure our parsing is OK */
		gnutls_assert();
		ret = GNUTLS_E_PARSING_ERROR;
		goto out_b64;
	}

	ret = GNUTLS_E_MEMORY_ERROR;
	enc_key.size = gnutls_cipher_get_key_size(cipher);
	enc_key.data = gnutls_malloc(enc_key.size);
	if (!enc_key.data) {
		ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
		goto out_b64;
	}

	key_data_size = b64_data.size;
	key_data = gnutls_malloc(key_data_size);
	if (!key_data) {
		ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
		goto out_enc_key;
	}

	while (1) {
		memcpy(key_data, b64_data.data, key_data_size);

		ret = openssl_hash_password(password, &enc_key, &salt);
		if (ret < 0) {
			gnutls_assert();
			goto out;
		}

		ret = gnutls_cipher_init(&handle, cipher, &enc_key, &salt);
		if (ret < 0) {
			gnutls_assert();
			gnutls_cipher_deinit(handle);
			goto out;
		}

		ret =
		    gnutls_cipher_decrypt(handle, key_data, key_data_size);
		gnutls_cipher_deinit(handle);

		if (ret < 0) {
			gnutls_assert();
			goto out;
		}

		/* We have to strip any padding to accept it.
		   So a bit more ASN.1 parsing for us. */
		if (key_data[0] == 0x30) {
			gnutls_datum_t key_datum;
			unsigned int blocksize =
			    gnutls_cipher_get_block_size(cipher);
			unsigned int keylen = key_data[1];
			unsigned int ofs = 2;

			if (keylen & 0x80) {
				int lenlen = keylen & 0x7f;
				keylen = 0;

				if (lenlen > 3) {
					gnutls_assert();
					goto fail;
				}

				while (lenlen) {
					keylen <<= 8;
					keylen |= key_data[ofs++];
					lenlen--;
				}
			}
			keylen += ofs;

			/* If there appears to be more padding than required, fail */
			if (key_data_size - keylen > blocksize) {
				gnutls_assert();
				goto fail;
			}

			/* If the padding bytes aren't all equal to the amount of padding, fail */
			ofs = keylen;
			while (ofs < key_data_size) {
				if (key_data[ofs] !=
				    key_data_size - keylen) {
					gnutls_assert();
					goto fail;
				}
				ofs++;
			}

			key_datum.data = key_data;
			key_datum.size = keylen;
			ret =
			    gnutls_x509_privkey_import(key, &key_datum,
						       GNUTLS_X509_FMT_DER);
			if (ret == 0)
				goto out;
		}
	      fail:
		ret = GNUTLS_E_DECRYPTION_FAILED;
		goto out;
	}
      out:
	zeroize_key(key_data, key_data_size);
	gnutls_free(key_data);
      out_enc_key:
	_gnutls_free_key_datum(&enc_key);
      out_b64:
	gnutls_free(b64_data.data);
      out_salt:
	gnutls_free(salt.data);
	return ret;
}
Ejemplo n.º 13
0
/* this function parses tpasswd.conf file. Format is:
 * string(username):base64(v):base64(salt):int(index)
 */
static int parse_tpasswd_values(SRP_PWD_ENTRY * entry, char *str)
{
	char *p;
	int len, ret;
	uint8_t *verifier;
	size_t verifier_size;
	int indx;

	p = strrchr(str, ':');	/* we have index */
	if (p == NULL) {
		gnutls_assert();
		return GNUTLS_E_SRP_PWD_PARSING_ERROR;
	}

	*p = '\0';
	p++;

	indx = atoi(p);
	if (indx == 0) {
		gnutls_assert();
		return GNUTLS_E_SRP_PWD_PARSING_ERROR;
	}

	/* now go for salt */
	p = strrchr(str, ':');	/* we have salt */
	if (p == NULL) {
		gnutls_assert();
		return GNUTLS_E_SRP_PWD_PARSING_ERROR;
	}

	*p = '\0';
	p++;

	len = strlen(p);

	entry->salt.size =
	    _gnutls_sbase64_decode(p, len, &entry->salt.data);

	if (entry->salt.size <= 0) {
		gnutls_assert();
		return GNUTLS_E_SRP_PWD_PARSING_ERROR;
	}

	/* now go for verifier */
	p = strrchr(str, ':');	/* we have verifier */
	if (p == NULL) {
		_gnutls_free_datum(&entry->salt);
		return GNUTLS_E_SRP_PWD_PARSING_ERROR;
	}

	*p = '\0';
	p++;

	len = strlen(p);
	ret = _gnutls_sbase64_decode(p, len, &verifier);
	if (ret <= 0) {
		gnutls_assert();
		_gnutls_free_datum(&entry->salt);
		return GNUTLS_E_SRP_PWD_PARSING_ERROR;
	}

	verifier_size = ret;
	entry->v.data = verifier;
	entry->v.size = verifier_size;

	/* now go for username */
	*p = '\0';

	entry->username = gnutls_strdup(str);
	if (entry->username == NULL) {
		_gnutls_free_datum(&entry->salt);
		_gnutls_free_key_datum(&entry->v);
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	return indx;
}
Ejemplo n.º 14
0
/* just read the username from the client key exchange.
 */
static int
_gnutls_proc_psk_client_kx(gnutls_session_t session, uint8_t * data,
			   size_t _data_size)
{
	ssize_t data_size = _data_size;
	int ret;
	gnutls_datum_t username, psk_key;
	gnutls_psk_server_credentials_t cred;
	psk_auth_info_t info;

	cred = (gnutls_psk_server_credentials_t)
	    _gnutls_get_cred(session, GNUTLS_CRD_PSK);

	if (cred == NULL) {
		gnutls_assert();
		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
	}

	if ((ret =
	     _gnutls_auth_info_set(session, GNUTLS_CRD_PSK,
				   sizeof(psk_auth_info_st), 1)) < 0) {
		gnutls_assert();
		return ret;
	}

	DECR_LEN(data_size, 2);
	username.size = _gnutls_read_uint16(&data[0]);

	DECR_LEN(data_size, username.size);

	username.data = &data[2];


	/* copy the username to the auth info structures
	 */
	info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
	if (info == NULL) {
		gnutls_assert();
		return GNUTLS_E_INTERNAL_ERROR;
	}

	if (username.size > MAX_USERNAME_SIZE) {
		gnutls_assert();
		return GNUTLS_E_ILLEGAL_SRP_USERNAME;
	}

	memcpy(info->username, username.data, username.size);
	info->username[username.size] = 0;

	ret =
	    _gnutls_psk_pwd_find_entry(session, info->username, &psk_key);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret = _gnutls_set_psk_session_key(session, &psk_key, NULL);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret = 0;

      error:
	_gnutls_free_key_datum(&psk_key);

	return ret;
}