formating

This commit is contained in:
lv-426 committed 2008-07-07 02:39:48 +00:00
1 parent b9f09651e6
commit 6d57794092
5 files changed
+2085 -2065

No files matched your search

+33 -28
View File
@@ -41,12 +41,13 @@
* Returns 0 on success.
*
**/
int gnutls_openpgp_keyring_init(gnutls_openpgp_keyring_t * keyring)
int
gnutls_openpgp_keyring_init (gnutls_openpgp_keyring_t * keyring)
{
*keyring = gnutls_calloc(1, sizeof(gnutls_openpgp_keyring_int));
*keyring = gnutls_calloc (1, sizeof (gnutls_openpgp_keyring_int));
if (*keyring)
return 0; /* success */
return 0; /* success */
return GNUTLS_E_MEMORY_ERROR;
}
@@ -57,26 +58,27 @@ int gnutls_openpgp_keyring_init(gnutls_openpgp_keyring_t * keyring)
* This function will deinitialize a keyring structure.
*
**/
void gnutls_openpgp_keyring_deinit(gnutls_openpgp_keyring_t keyring)
void
gnutls_openpgp_keyring_deinit (gnutls_openpgp_keyring_t keyring)
{
if (!keyring)
return;
if (keyring->db)
{
cdk_keydb_free(keyring->db);
cdk_keydb_free (keyring->db);
keyring->db = NULL;
}
/* In some cases the stream is also stored outside the keydb context
and we need to close it here then. */
and we need to close it here then. */
if (keyring->db_stream)
{
cdk_stream_close(keyring->db_stream);
cdk_stream_close (keyring->db_stream);
keyring->db_stream = NULL;
}
gnutls_free(keyring);
gnutls_free (keyring);
}
/**
@@ -90,19 +92,20 @@ void gnutls_openpgp_keyring_deinit(gnutls_openpgp_keyring_t keyring)
* Returns 0 on success (if keyid exists) and a negative error code
* on failure.
**/
int gnutls_openpgp_keyring_check_id(gnutls_openpgp_keyring_t ring,
const unsigned char keyid[8],
unsigned int flags)
int
gnutls_openpgp_keyring_check_id (gnutls_openpgp_keyring_t ring,
const unsigned char keyid[8],
unsigned int flags)
{
cdk_pkt_pubkey_t pk;
uint32_t id[2];
id[0] = _gnutls_read_uint32(keyid);
id[1] = _gnutls_read_uint32(&keyid[4]);
id[0] = _gnutls_read_uint32 (keyid);
id[1] = _gnutls_read_uint32 (&keyid[4]);
if (!cdk_keydb_get_pk(ring->db, id, &pk))
if (!cdk_keydb_get_pk (ring->db, id, &pk))
{
cdk_pk_release(pk);
cdk_pk_release (pk);
return 0;
}
@@ -123,42 +126,44 @@ int gnutls_openpgp_keyring_check_id(gnutls_openpgp_keyring_t ring,
* Returns 0 on success.
*
**/
int gnutls_openpgp_keyring_import(gnutls_openpgp_keyring_t keyring,
const gnutls_datum_t * data,
gnutls_openpgp_crt_fmt_t format)
int
gnutls_openpgp_keyring_import (gnutls_openpgp_keyring_t keyring,
const gnutls_datum_t * data,
gnutls_openpgp_crt_fmt_t format)
{
cdk_error_t err;
cdk_stream_t input;
_gnutls_debug_log ("PGP: keyring import format '%s'\n",
format == GNUTLS_OPENPGP_FMT_RAW ? "raw" : "base64");
format == GNUTLS_OPENPGP_FMT_RAW ? "raw" : "base64");
if (format == GNUTLS_OPENPGP_FMT_RAW)
{
err
= cdk_keydb_new(&keyring->db, CDK_DBTYPE_DATA, data->data, data->size);
=
cdk_keydb_new (&keyring->db, CDK_DBTYPE_DATA, data->data, data->size);
if (err)
gnutls_assert ();
return _gnutls_map_cdk_rc (err);
}
/* Create a new stream from the given data, which means to
allocate a new stream and to write the data in the stream.
Then push the armor filter to decode the data and to store
it in the raw format. */
err = cdk_stream_tmp_from_mem(data->data, data->size, &input);
allocate a new stream and to write the data in the stream.
Then push the armor filter to decode the data and to store
it in the raw format. */
err = cdk_stream_tmp_from_mem (data->data, data->size, &input);
if (!err)
err = cdk_stream_set_armor_flag(input, 0);
err = cdk_stream_set_armor_flag (input, 0);
if (!err)
err = cdk_keydb_new_from_stream(&keyring->db, 0, input);
err = cdk_keydb_new_from_stream (&keyring->db, 0, input);
if (err)
{
cdk_stream_close(input);
cdk_stream_close (input);
gnutls_assert ();
}
else
/* The keydb function will not close the stream itself, so we need to
store it separately to close it later. */
store it separately to close it later. */
keyring->db_stream = input;
return _gnutls_map_cdk_rc (err);
+89 -80
View File
@@ -39,12 +39,13 @@
* Returns 0 on success.
*
**/
int gnutls_openpgp_crt_init(gnutls_openpgp_crt_t * key)
int
gnutls_openpgp_crt_init (gnutls_openpgp_crt_t * key)
{
*key = gnutls_calloc(1, sizeof(gnutls_openpgp_crt_int));
*key = gnutls_calloc (1, sizeof (gnutls_openpgp_crt_int));
if (*key)
return 0; /* success */
return 0; /* success */
return GNUTLS_E_MEMORY_ERROR;
}
@@ -54,18 +55,19 @@ int gnutls_openpgp_crt_init(gnutls_openpgp_crt_t * key)
*
* This function will deinitialize a key structure.
**/
void gnutls_openpgp_crt_deinit(gnutls_openpgp_crt_t key)
void
gnutls_openpgp_crt_deinit (gnutls_openpgp_crt_t key)
{
if (!key)
return;
if (key->knode)
{
cdk_kbnode_release(key->knode);
cdk_kbnode_release (key->knode);
key->knode = NULL;
}
gnutls_free(key);
gnutls_free (key);
}
/**
@@ -79,32 +81,33 @@ void gnutls_openpgp_crt_deinit(gnutls_openpgp_crt_t key)
*
* Returns 0 on success.
**/
int gnutls_openpgp_crt_import(gnutls_openpgp_crt_t key,
const gnutls_datum_t * data,
gnutls_openpgp_crt_fmt_t format)
int
gnutls_openpgp_crt_import (gnutls_openpgp_crt_t key,
const gnutls_datum_t * data,
gnutls_openpgp_crt_fmt_t format)
{
cdk_stream_t inp;
int rc;
if (format == GNUTLS_OPENPGP_FMT_RAW)
rc = cdk_kbnode_read_from_mem(&key->knode, data->data, data->size);
rc = cdk_kbnode_read_from_mem (&key->knode, data->data, data->size);
else
{
rc = cdk_stream_tmp_from_mem(data->data, data->size, &inp);
rc = cdk_stream_tmp_from_mem (data->data, data->size, &inp);
if (rc)
{
rc = _gnutls_map_cdk_rc(rc);
rc = _gnutls_map_cdk_rc (rc);
gnutls_assert ();
return rc;
}
if (cdk_armor_filter_use(inp))
rc = cdk_stream_set_armor_flag(inp, 0);
if (cdk_armor_filter_use (inp))
rc = cdk_stream_set_armor_flag (inp, 0);
if (!rc)
rc = cdk_keydb_get_keyblock(inp, &key->knode);
cdk_stream_close(inp);
rc = cdk_keydb_get_keyblock (inp, &key->knode);
cdk_stream_close (inp);
if (rc)
{
rc = _gnutls_map_cdk_rc(rc);
rc = _gnutls_map_cdk_rc (rc);
gnutls_assert ();
return rc;
}
@@ -127,50 +130,50 @@ int gnutls_openpgp_crt_import(gnutls_openpgp_crt_t key,
* Returns 0 on success.
*
**/
int gnutls_openpgp_crt_export(gnutls_openpgp_crt_t key,
gnutls_openpgp_crt_fmt_t format,
void *output_data,
size_t * output_data_size)
int
gnutls_openpgp_crt_export (gnutls_openpgp_crt_t key,
gnutls_openpgp_crt_fmt_t format,
void *output_data, size_t * output_data_size)
{
size_t input_data_size = *output_data_size;
size_t calc_size;
int rc;
rc = cdk_kbnode_write_to_mem(key->knode, output_data, output_data_size);
rc = cdk_kbnode_write_to_mem (key->knode, output_data, output_data_size);
if (rc)
{
rc = _gnutls_map_cdk_rc(rc);
rc = _gnutls_map_cdk_rc (rc);
gnutls_assert ();
return rc;
}
/* FIXME: The first call of this function is with output_data == NULL
to figure out the size and the caller expects this error here. */
to figure out the size and the caller expects this error here. */
if (!output_data)
return GNUTLS_E_SHORT_MEMORY_BUFFER;
if (format == GNUTLS_OPENPGP_FMT_BASE64)
{
unsigned char *in = cdk_calloc(1, *output_data_size);
memcpy(in, output_data, *output_data_size);
unsigned char *in = cdk_calloc (1, *output_data_size);
memcpy (in, output_data, *output_data_size);
/* Calculate the size of the encoded data and check if the provided
buffer is large enough. */
rc = cdk_armor_encode_buffer(in, input_data_size,
NULL, 0, &calc_size, CDK_ARMOR_PUBKEY);
buffer is large enough. */
rc = cdk_armor_encode_buffer (in, input_data_size,
NULL, 0, &calc_size, CDK_ARMOR_PUBKEY);
if (rc || calc_size > input_data_size)
{
cdk_free(in);
cdk_free (in);
*output_data_size = calc_size;
rc = _gnutls_map_cdk_rc(CDK_Too_Short);
rc = _gnutls_map_cdk_rc (CDK_Too_Short);
gnutls_assert ();
return rc;
}
rc = cdk_armor_encode_buffer(in, input_data_size, output_data,
input_data_size, &calc_size,
CDK_ARMOR_PUBKEY);
cdk_free(in);
rc = cdk_armor_encode_buffer (in, input_data_size, output_data,
input_data_size, &calc_size,
CDK_ARMOR_PUBKEY);
cdk_free (in);
*output_data_size = calc_size;
}
@@ -186,12 +189,12 @@ int gnutls_openpgp_crt_export(gnutls_openpgp_crt_t key,
* Returns the fingerprint of the OpenPGP key. Depends on the algorithm,
* the fingerprint can be 16 or 20 bytes.
**/
int gnutls_openpgp_crt_get_fingerprint(gnutls_openpgp_crt_t key,
void *fpr,
size_t * fprlen)
int
gnutls_openpgp_crt_get_fingerprint (gnutls_openpgp_crt_t key,
void *fpr, size_t * fprlen)
{
cdk_packet_t pkt;
cdk_pkt_pubkey_t pk= NULL;
cdk_pkt_pubkey_t pk = NULL;
if (!fpr || !fprlen)
{
@@ -201,7 +204,7 @@ int gnutls_openpgp_crt_get_fingerprint(gnutls_openpgp_crt_t key,
*fprlen = 0;
pkt = cdk_kbnode_find_packet(key->knode, CDK_PKT_PUBLIC_KEY);
pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
if (!pkt)
return GNUTLS_E_OPENPGP_GETKEY_FAILED;
@@ -211,12 +214,13 @@ int gnutls_openpgp_crt_get_fingerprint(gnutls_openpgp_crt_t key,
/* FIXME: Check if the draft allows old PGP keys. */
if (is_RSA (pk->pubkey_algo) && pk->version < 4)
*fprlen = 16;
cdk_pk_get_fingerprint(pk, fpr);
cdk_pk_get_fingerprint (pk, fpr);
return 0;
}
int _gnutls_openpgp_count_key_names(gnutls_openpgp_crt_t key)
int
_gnutls_openpgp_count_key_names (gnutls_openpgp_crt_t key)
{
cdk_kbnode_t p, ctx;
cdk_packet_t pkt;
@@ -230,9 +234,9 @@ int _gnutls_openpgp_count_key_names(gnutls_openpgp_crt_t key)
ctx = NULL;
nuids = 0;
while ((p = cdk_kbnode_walk(key->knode, &ctx, 0)))
while ((p = cdk_kbnode_walk (key->knode, &ctx, 0)))
{
pkt = cdk_kbnode_get_packet(p);
pkt = cdk_kbnode_get_packet (p);
if (pkt->pkttype == CDK_PKT_USER_ID)
nuids++;
}
@@ -254,14 +258,13 @@ int _gnutls_openpgp_count_key_names(gnutls_openpgp_crt_t key)
* if the index of the ID does not exist.
*
**/
int gnutls_openpgp_crt_get_name(gnutls_openpgp_crt_t key,
int idx,
char *buf,
size_t * sizeof_buf)
int
gnutls_openpgp_crt_get_name (gnutls_openpgp_crt_t key,
int idx, char *buf, size_t * sizeof_buf)
{
cdk_kbnode_t ctx= NULL, p;
cdk_packet_t pkt= NULL;
cdk_pkt_userid_t uid= NULL;
cdk_kbnode_t ctx = NULL, p;
cdk_packet_t pkt = NULL;
cdk_pkt_userid_t uid = NULL;
int pos = 0;
if (!key || !buf)
@@ -270,17 +273,17 @@ int gnutls_openpgp_crt_get_name(gnutls_openpgp_crt_t key,
return GNUTLS_E_INVALID_REQUEST;
}
if (idx < 0 || idx > _gnutls_openpgp_count_key_names(key))
if (idx < 0 || idx > _gnutls_openpgp_count_key_names (key))
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
if (!idx)
pkt = cdk_kbnode_find_packet(key->knode, CDK_PKT_USER_ID);
pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_USER_ID);
else
{
pos = 0;
while ((p = cdk_kbnode_walk(key->knode, &ctx, 0)))
while ((p = cdk_kbnode_walk (key->knode, &ctx, 0)))
{
pkt = cdk_kbnode_get_packet(p);
pkt = cdk_kbnode_get_packet (p);
if (pkt->pkttype == CDK_PKT_USER_ID && ++pos == idx)
break;
}
@@ -300,8 +303,8 @@ int gnutls_openpgp_crt_get_name(gnutls_openpgp_crt_t key,
return GNUTLS_E_SHORT_MEMORY_BUFFER;
}
memcpy(buf, uid->name, uid->len);
buf[uid->len] = '\0'; /* make sure it's a string */
memcpy (buf, uid->name, uid->len);
buf[uid->len] = '\0'; /* make sure it's a string */
*sizeof_buf = uid->len + 1;
if (uid->is_revoked)
@@ -326,8 +329,9 @@ int gnutls_openpgp_crt_get_name(gnutls_openpgp_crt_t key,
* or a negative value on error.
*
**/
gnutls_pk_algorithm_t gnutls_openpgp_crt_get_pk_algorithm(gnutls_openpgp_crt_t key,
unsigned int *bits)
gnutls_pk_algorithm_t
gnutls_openpgp_crt_get_pk_algorithm (gnutls_openpgp_crt_t key,
unsigned int *bits)
{
cdk_packet_t pkt;
int algo;
@@ -336,11 +340,11 @@ gnutls_pk_algorithm_t gnutls_openpgp_crt_get_pk_algorithm(gnutls_openpgp_crt_t k
return GNUTLS_PK_UNKNOWN;
algo = 0;
pkt = cdk_kbnode_find_packet(key->knode, CDK_PKT_PUBLIC_KEY);
pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
if (pkt && pkt->pkttype == CDK_PKT_PUBLIC_KEY)
{
if (bits)
*bits = cdk_pk_get_nbits(pkt->pkt.public_key);
*bits = cdk_pk_get_nbits (pkt->pkt.public_key);
algo = pkt->pkt.public_key->pubkey_algo;
if (is_RSA (algo))
algo = GNUTLS_PK_RSA;
@@ -357,7 +361,8 @@ gnutls_pk_algorithm_t gnutls_openpgp_crt_get_pk_algorithm(gnutls_openpgp_crt_t k
*
* Extract the version of the OpenPGP key.
**/
int gnutls_openpgp_crt_get_version(gnutls_openpgp_crt_t key)
int
gnutls_openpgp_crt_get_version (gnutls_openpgp_crt_t key)
{
cdk_packet_t pkt;
int version;
@@ -365,7 +370,7 @@ int gnutls_openpgp_crt_get_version(gnutls_openpgp_crt_t key)
if (!key)
return -1;
pkt = cdk_kbnode_find_packet(key->knode, CDK_PKT_PUBLIC_KEY);
pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
if (pkt)
version = pkt->pkt.public_key->version;
else
@@ -380,7 +385,8 @@ int gnutls_openpgp_crt_get_version(gnutls_openpgp_crt_t key)
*
* Returns the timestamp when the OpenPGP key was created.
**/
time_t gnutls_openpgp_crt_get_creation_time(gnutls_openpgp_crt_t key)
time_t
gnutls_openpgp_crt_get_creation_time (gnutls_openpgp_crt_t key)
{
cdk_packet_t pkt;
time_t timestamp;
@@ -388,7 +394,7 @@ time_t gnutls_openpgp_crt_get_creation_time(gnutls_openpgp_crt_t key)
if (!key)
return (time_t) - 1;
pkt = cdk_kbnode_find_packet(key->knode, CDK_PKT_PUBLIC_KEY);
pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
if (pkt)
timestamp = pkt->pkt.public_key->timestamp;
else
@@ -404,7 +410,8 @@ time_t gnutls_openpgp_crt_get_creation_time(gnutls_openpgp_crt_t key)
* Returns the time when the OpenPGP key expires. A value of '0' means
* that the key doesn't expire at all.
**/
time_t gnutls_openpgp_crt_get_expiration_time(gnutls_openpgp_crt_t key)
time_t
gnutls_openpgp_crt_get_expiration_time (gnutls_openpgp_crt_t key)
{
cdk_packet_t pkt;
time_t expiredate;
@@ -412,7 +419,7 @@ time_t gnutls_openpgp_crt_get_expiration_time(gnutls_openpgp_crt_t key)
if (!key)
return (time_t) - 1;
pkt = cdk_kbnode_find_packet(key->knode, CDK_PKT_PUBLIC_KEY);
pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
if (pkt)
expiredate = pkt->pkt.public_key->expiredate;
else
@@ -428,8 +435,8 @@ time_t gnutls_openpgp_crt_get_expiration_time(gnutls_openpgp_crt_t key)
*
* Returns the 64-bit keyID of the OpenPGP key.
**/
int gnutls_openpgp_crt_get_id(gnutls_openpgp_crt_t key,
unsigned char keyid[8])
int
gnutls_openpgp_crt_get_id (gnutls_openpgp_crt_t key, unsigned char keyid[8])
{
cdk_packet_t pkt;
uint32_t kid[2];
@@ -440,11 +447,11 @@ int gnutls_openpgp_crt_get_id(gnutls_openpgp_crt_t key,
return GNUTLS_E_INVALID_REQUEST;
}
pkt = cdk_kbnode_find_packet(key->knode, CDK_PKT_PUBLIC_KEY);
pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
if (!pkt)
return GNUTLS_E_OPENPGP_GETKEY_FAILED;
cdk_pk_get_keyid(pkt->pkt.public_key, kid);
cdk_pk_get_keyid (pkt->pkt.public_key, kid);
keyid[0] = kid[0] >> 24;
keyid[1] = kid[0] >> 16;
keyid[2] = kid[0] >> 8;
@@ -469,8 +476,9 @@ int gnutls_openpgp_crt_get_id(gnutls_openpgp_crt_t key,
* Returns non zero on success, and zero on failure.
*
**/
int gnutls_openpgp_crt_check_hostname(gnutls_openpgp_crt_t key,
const char *hostname)
int
gnutls_openpgp_crt_check_hostname (gnutls_openpgp_crt_t key,
const char *hostname)
{
char dnsname[MAX_CN];
size_t dnsnamesize;
@@ -481,9 +489,9 @@ int gnutls_openpgp_crt_check_hostname(gnutls_openpgp_crt_t key,
for (i = 0; !(ret < 0); i++)
{
dnsnamesize = sizeof (dnsname);
ret = gnutls_openpgp_crt_get_name(key, i, dnsname, &dnsnamesize);
ret = gnutls_openpgp_crt_get_name (key, i, dnsname, &dnsnamesize);
/* FIXME: ret is not used */
if (_gnutls_hostname_compare(dnsname, hostname))
if (_gnutls_hostname_compare (dnsname, hostname))
return 1;
}
@@ -503,8 +511,9 @@ int gnutls_openpgp_crt_check_hostname(gnutls_openpgp_crt_t key,
* A negative value may be returned in case of parsing error.
*
*/
int gnutls_openpgp_crt_get_key_usage(gnutls_openpgp_crt_t key,
unsigned int *key_usage)
int
gnutls_openpgp_crt_get_key_usage (gnutls_openpgp_crt_t key,
unsigned int *key_usage)
{
cdk_packet_t pkt;
int algo = 0;
@@ -514,14 +523,14 @@ int gnutls_openpgp_crt_get_key_usage(gnutls_openpgp_crt_t key,
*key_usage = 0;
pkt = cdk_kbnode_find_packet(key->knode, CDK_PKT_PUBLIC_KEY);
pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
if (pkt && pkt->pkttype == CDK_PKT_PUBLIC_KEY)
{
algo = pkt->pkt.public_key->pubkey_algo;
/* FIXME: We need to take a look at the key flags because
RSA-E and RSA-S are obsolete. Only RSA is used
and the flags are used to set the capabilities. */
RSA-E and RSA-S are obsolete. Only RSA is used
and the flags are used to set the capabilities. */
if (is_DSA (algo) || algo == GCRY_PK_RSA_S)
*key_usage |= KEY_DIGITAL_SIGNATURE;
else if (algo == GCRY_PK_RSA_E)
+333 -320
View File
@@ -50,13 +50,15 @@
*
* Returns: the version of the currently used protocol.
**/
gnutls_protocol_t gnutls_protocol_get_version(gnutls_session_t session)
gnutls_protocol_t
gnutls_protocol_get_version (gnutls_session_t session)
{
return session->security_parameters.version;
}
void _gnutls_set_current_version(gnutls_session_t session,
gnutls_protocol_t version)
void
_gnutls_set_current_version (gnutls_session_t session,
gnutls_protocol_t version)
{
session->security_parameters.version = version;
}
@@ -73,8 +75,8 @@ void _gnutls_set_current_version(gnutls_session_t session,
* berkeley style sockets. Otherwise it must be called and set lowat
* to zero.
**/
void gnutls_transport_set_lowat(gnutls_session_t session,
int num)
void
gnutls_transport_set_lowat (gnutls_session_t session, int num)
{
session->internals.lowat = num;
}
@@ -91,7 +93,8 @@ void gnutls_transport_set_lowat(gnutls_session_t session,
* Normally only servers that require maximum compatibility with everything
* out there, need to call this function.
**/
void gnutls_record_disable_padding(gnutls_session_t session)
void
gnutls_record_disable_padding (gnutls_session_t session)
{
session->internals.priorities.no_padding = 1;
}
@@ -105,8 +108,9 @@ void gnutls_record_disable_padding(gnutls_session_t session)
* PUSH and PULL). In berkeley style sockets this function will set
* the connection handle.
**/
void gnutls_transport_set_ptr(gnutls_session_t session,
gnutls_transport_ptr_t ptr)
void
gnutls_transport_set_ptr (gnutls_session_t session,
gnutls_transport_ptr_t ptr)
{
session->internals.transport_recv_ptr = ptr;
session->internals.transport_send_ptr = ptr;
@@ -123,9 +127,10 @@ void gnutls_transport_set_ptr(gnutls_session_t session,
* the connection handle. With this function you can use two
* different pointers for receiving and sending.
**/
void gnutls_transport_set_ptr2(gnutls_session_t session,
gnutls_transport_ptr_t recv_ptr,
gnutls_transport_ptr_t send_ptr)
void
gnutls_transport_set_ptr2 (gnutls_session_t session,
gnutls_transport_ptr_t recv_ptr,
gnutls_transport_ptr_t send_ptr)
{
session->internals.transport_send_ptr = send_ptr;
session->internals.transport_recv_ptr = recv_ptr;
@@ -141,7 +146,8 @@ void gnutls_transport_set_ptr2(gnutls_session_t session,
*
* Returns: first argument of the transport function.
**/
gnutls_transport_ptr_t gnutls_transport_get_ptr(gnutls_session_t session)
gnutls_transport_ptr_t
gnutls_transport_get_ptr (gnutls_session_t session)
{
return session->internals.transport_recv_ptr;
}
@@ -156,9 +162,10 @@ gnutls_transport_ptr_t gnutls_transport_get_ptr(gnutls_session_t session)
* and PULL). These should have been set using
* gnutls_transport_set_ptr2().
**/
void gnutls_transport_get_ptr2(gnutls_session_t session,
gnutls_transport_ptr_t * recv_ptr,
gnutls_transport_ptr_t * send_ptr)
void
gnutls_transport_get_ptr2 (gnutls_session_t session,
gnutls_transport_ptr_t * recv_ptr,
gnutls_transport_ptr_t * send_ptr)
{
*recv_ptr = session->internals.transport_recv_ptr;
@@ -198,58 +205,59 @@ void gnutls_transport_get_ptr2(gnutls_session_t session,
* Returns: %GNUTLS_E_SUCCESS on success, or an error code, see
* function documentation for entire semantics.
**/
int gnutls_bye(gnutls_session_t session,
gnutls_close_request_t how)
int
gnutls_bye (gnutls_session_t session, gnutls_close_request_t how)
{
int ret = 0;
switch (STATE)
{
case STATE0:
case STATE60:
ret = _gnutls_io_write_flush(session);
STATE = STATE60;
if (ret < 0)
{
gnutls_assert ();
return ret;
}
case STATE0:
case STATE60:
ret = _gnutls_io_write_flush (session);
STATE = STATE60;
if (ret < 0)
{
gnutls_assert ();
return ret;
}
case STATE61:
ret = gnutls_alert_send(session, GNUTLS_AL_WARNING, GNUTLS_A_CLOSE_NOTIFY);
STATE = STATE61;
if (ret < 0)
{
gnutls_assert ();
return ret;
}
case STATE61:
ret =
gnutls_alert_send (session, GNUTLS_AL_WARNING, GNUTLS_A_CLOSE_NOTIFY);
STATE = STATE61;
if (ret < 0)
{
gnutls_assert ();
return ret;
}
case STATE62:
STATE = STATE62;
if (how == GNUTLS_SHUT_RDWR)
{
do
{
_gnutls_io_clear_peeked_data(session);
ret = _gnutls_recv_int(session, GNUTLS_ALERT, -1, NULL, 0);
} while (ret == GNUTLS_E_GOT_APPLICATION_DATA);
case STATE62:
STATE = STATE62;
if (how == GNUTLS_SHUT_RDWR)
{
do
{
_gnutls_io_clear_peeked_data (session);
ret = _gnutls_recv_int (session, GNUTLS_ALERT, -1, NULL, 0);
}
while (ret == GNUTLS_E_GOT_APPLICATION_DATA);
if (ret >= 0)
session->internals.may_not_read = 1;
if (ret >= 0)
session->internals.may_not_read = 1;
if (ret < 0)
{
gnutls_assert ();
return ret;
}
}
STATE = STATE62;
if (ret < 0)
{
gnutls_assert ();
return ret;
}
}
STATE = STATE62;
break;
default:
gnutls_assert ()
;
return GNUTLS_E_INTERNAL_ERROR;
break;
default:
gnutls_assert ();
return GNUTLS_E_INTERNAL_ERROR;
}
STATE = STATE0;
@@ -258,19 +266,22 @@ int gnutls_bye(gnutls_session_t session,
return 0;
}
inline static void session_invalidate(gnutls_session_t session)
inline static void
session_invalidate (gnutls_session_t session)
{
session->internals.valid_connection = VALID_FALSE;
}
inline static void session_unresumable(gnutls_session_t session)
inline static void
session_unresumable (gnutls_session_t session)
{
session->internals.resumable = RESUME_FALSE;
}
/* returns 0 if session is valid
*/
inline static int session_is_valid(gnutls_session_t session)
inline static int
session_is_valid (gnutls_session_t session)
{
if (session->internals.valid_connection == VALID_FALSE)
return GNUTLS_E_INVALID_SESSION;
@@ -281,19 +292,19 @@ inline static int session_is_valid(gnutls_session_t session)
/* Copies the record version into the headers. The
* version must have 2 bytes at least.
*/
inline static void copy_record_version(gnutls_session_t session,
gnutls_handshake_description_t htype,
opaque version[2])
inline static void
copy_record_version (gnutls_session_t session,
gnutls_handshake_description_t htype, opaque version[2])
{
gnutls_protocol_t lver;
if (htype != GNUTLS_HANDSHAKE_CLIENT_HELLO
|| session->internals.default_record_version[0] == 0)
{
lver = gnutls_protocol_get_version(session);
lver = gnutls_protocol_get_version (session);
version[0] = _gnutls_version_get_major(lver);
version[1] = _gnutls_version_get_minor(lver);
version[0] = _gnutls_version_get_major (lver);
version[1] = _gnutls_version_get_minor (lver);
}
else
{
@@ -316,11 +327,11 @@ inline static void copy_record_version(gnutls_session_t session,
* and only if the previous send was interrupted for some reason.
*
*/
ssize_t _gnutls_send_int(gnutls_session_t session,
content_type_t type,
gnutls_handshake_description_t htype,
const void *_data,
size_t sizeofdata)
ssize_t
_gnutls_send_int (gnutls_session_t session,
content_type_t type,
gnutls_handshake_description_t htype,
const void *_data, size_t sizeofdata)
{
uint8_t *cipher;
int cipher_size;
@@ -334,14 +345,14 @@ ssize_t _gnutls_send_int(gnutls_session_t session,
* ok, and means to resume.
*/
if (session->internals.record_send_buffer.length == 0 && (sizeofdata == 0
&& _data == NULL))
&& _data == NULL))
{
gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
if (type != GNUTLS_ALERT) /* alert messages are sent anyway */
if (session_is_valid(session) || session->internals.may_not_write != 0)
if (type != GNUTLS_ALERT) /* alert messages are sent anyway */
if (session_is_valid (session) || session->internals.may_not_write != 0)
{
gnutls_assert ();
return GNUTLS_E_INVALID_SESSION;
@@ -352,13 +363,13 @@ ssize_t _gnutls_send_int(gnutls_session_t session,
/* Use the default record version, if it is
* set.
*/
copy_record_version(session, htype, &headers[1]);
copy_record_version (session, htype, &headers[1]);
_gnutls_record_log
("REC[%x]: Sending Packet[%d] %s(%d) with length: %d\n", session,
(int) _gnutls_uint64touint32 (&session->connection_state.
write_sequence_number),
_gnutls_packet2str (type), type, sizeofdata);
("REC[%x]: Sending Packet[%d] %s(%d) with length: %d\n", session,
(int) _gnutls_uint64touint32 (&session->connection_state.
write_sequence_number),
_gnutls_packet2str (type), type, sizeofdata);
if (sizeofdata > MAX_RECORD_SEND_SIZE)
data2send_size = MAX_RECORD_SEND_SIZE;
@@ -370,7 +381,7 @@ ssize_t _gnutls_send_int(gnutls_session_t session,
*/
if (session->internals.record_send_buffer.length > 0)
{
ret = _gnutls_io_write_flush(session);
ret = _gnutls_io_write_flush (session);
if (ret > 0)
cipher_size = ret;
else
@@ -384,7 +395,8 @@ ssize_t _gnutls_send_int(gnutls_session_t session,
{
/* now proceed to packet encryption
*/
cipher_size = data2send_size + MAX_RECORD_OVERHEAD;cipher = gnutls_malloc (cipher_size);
cipher_size = data2send_size + MAX_RECORD_OVERHEAD;
cipher = gnutls_malloc (cipher_size);
if (cipher == NULL)
{
gnutls_assert ();
@@ -392,17 +404,17 @@ ssize_t _gnutls_send_int(gnutls_session_t session,
}
cipher_size =
_gnutls_encrypt (session, headers, RECORD_HEADER_SIZE, data,
data2send_size, cipher, cipher_size, type,
(session->internals.priorities.no_padding ==
0) ? 1 : 0);
_gnutls_encrypt (session, headers, RECORD_HEADER_SIZE, data,
data2send_size, cipher, cipher_size, type,
(session->internals.priorities.no_padding ==
0) ? 1 : 0);
if (cipher_size <= 0)
{
gnutls_assert ();
if (cipher_size == 0)
cipher_size = GNUTLS_E_ENCRYPTION_FAILED;
cipher_size = GNUTLS_E_ENCRYPTION_FAILED;
gnutls_free (cipher);
return cipher_size; /* error */
return cipher_size; /* error */
}
retval = data2send_size;
@@ -434,7 +446,7 @@ ssize_t _gnutls_send_int(gnutls_session_t session,
return ret;
}
if (ret> 0)
if (ret > 0)
{
gnutls_assert ();
ret = GNUTLS_E_INTERNAL_ERROR;
@@ -448,11 +460,11 @@ ssize_t _gnutls_send_int(gnutls_session_t session,
session->internals.record_send_buffer_user_size = 0;
_gnutls_record_log ("REC[%x]: Sent Packet[%d] %s(%d) with length: %d\n",
session,
(int) _gnutls_uint64touint32 (&session->
connection_state.
write_sequence_number),
_gnutls_packet2str (type), type, cipher_size);
session,
(int) _gnutls_uint64touint32 (&session->
connection_state.
write_sequence_number),
_gnutls_packet2str (type), type, cipher_size);
return retval;
}
@@ -460,37 +472,37 @@ ssize_t _gnutls_send_int(gnutls_session_t session,
/* This function is to be called if the handshake was successfully
* completed. This sends a Change Cipher Spec packet to the peer.
*/
ssize_t _gnutls_send_change_cipher_spec(gnutls_session_t session,
int again)
ssize_t
_gnutls_send_change_cipher_spec (gnutls_session_t session, int again)
{
static const opaque data[1] =
{
GNUTLS_TYPE_CHANGE_CIPHER_SPEC };
static const opaque data[1] = {
GNUTLS_TYPE_CHANGE_CIPHER_SPEC
};
_gnutls_handshake_log ("REC[%x]: Sent ChangeCipherSpec\n", session);
if (again == 0)
return _gnutls_send_int(session, GNUTLS_CHANGE_CIPHER_SPEC, -1, data, 1);
return _gnutls_send_int (session, GNUTLS_CHANGE_CIPHER_SPEC, -1, data, 1);
else
{
return _gnutls_io_write_flush(session);
return _gnutls_io_write_flush (session);
}
}
inline static int check_recv_type(content_type_t recv_type)
inline static int
check_recv_type (content_type_t recv_type)
{
switch (recv_type)
{
case GNUTLS_CHANGE_CIPHER_SPEC:
case GNUTLS_ALERT:
case GNUTLS_HANDSHAKE:
case GNUTLS_APPLICATION_DATA:
case GNUTLS_INNER_APPLICATION:
return 0;
default:
gnutls_assert ()
;
return GNUTLS_A_UNEXPECTED_MESSAGE;
case GNUTLS_CHANGE_CIPHER_SPEC:
case GNUTLS_ALERT:
case GNUTLS_HANDSHAKE:
case GNUTLS_APPLICATION_DATA:
case GNUTLS_INNER_APPLICATION:
return 0;
default:
gnutls_assert ();
return GNUTLS_A_UNEXPECTED_MESSAGE;
}
}
@@ -498,18 +510,17 @@ inline static int check_recv_type(content_type_t recv_type)
/* Checks if there are pending data in the record buffers. If there are
* then it copies the data.
*/
static int check_buffers(gnutls_session_t session,
content_type_t type,
opaque * data,
int sizeofdata)
static int
check_buffers (gnutls_session_t session,
content_type_t type, opaque * data, int sizeofdata)
{
if ((type == GNUTLS_APPLICATION_DATA || type == GNUTLS_HANDSHAKE || type
== GNUTLS_INNER_APPLICATION) && _gnutls_record_buffer_get_size(type,
session)
== GNUTLS_INNER_APPLICATION) && _gnutls_record_buffer_get_size (type,
session)
> 0)
{
int ret, ret2;
ret = _gnutls_record_buffer_get(type, session, data, sizeofdata);
ret = _gnutls_record_buffer_get (type, session, data, sizeofdata);
if (ret < 0)
{
gnutls_assert ();
@@ -517,9 +528,9 @@ static int check_buffers(gnutls_session_t session,
}
/* if the buffer just got empty */
if (_gnutls_record_buffer_get_size(type, session) == 0)
if (_gnutls_record_buffer_get_size (type, session) == 0)
{
if ((ret2 = _gnutls_io_clear_peeked_data(session)) < 0)
if ((ret2 = _gnutls_io_clear_peeked_data (session)) < 0)
{
gnutls_assert ();
return ret2;
@@ -535,14 +546,14 @@ static int check_buffers(gnutls_session_t session,
/* Checks the record headers and returns the length, version and
* content type.
*/
static int record_check_headers(gnutls_session_t session,
uint8_t headers[RECORD_HEADER_SIZE],
content_type_t type,
gnutls_handshake_description_t htype,
/*output */content_type_t * recv_type,
opaque version[2],
uint16_t * length,
uint16_t * header_size)
static int
record_check_headers (gnutls_session_t session,
uint8_t headers[RECORD_HEADER_SIZE],
content_type_t type,
gnutls_handshake_description_t htype,
/*output */ content_type_t * recv_type,
opaque version[2],
uint16_t * length, uint16_t * header_size)
{
/* Read the first two bytes to determine if this is a
@@ -556,15 +567,15 @@ static int record_check_headers(gnutls_session_t session,
/* if msb set and expecting handshake message
* it should be SSL 2 hello
*/
version[0] = 3; /* assume SSL 3.0 */
version[0] = 3; /* assume SSL 3.0 */
version[1] = 0;
*length = (((headers[0] & 0x7f) << 8)) | headers[1];
/* SSL 2.0 headers */
*header_size = 2;
*recv_type = GNUTLS_HANDSHAKE; /* we accept only v2 client hello
*/
*recv_type = GNUTLS_HANDSHAKE; /* we accept only v2 client hello
*/
/* in order to assist the handshake protocol.
* V2 compatibility is a mess.
@@ -572,7 +583,7 @@ static int record_check_headers(gnutls_session_t session,
session->internals.v2_hello = *length;
_gnutls_record_log ("REC[%x]: V2 packet received. Length: %d\n",
session, *length);
session, *length);
}
else
@@ -584,7 +595,7 @@ static int record_check_headers(gnutls_session_t session,
/* No DECR_LEN, since headers has enough size.
*/
*length = _gnutls_read_uint16(&headers[3]);
*length = _gnutls_read_uint16 (&headers[3]);
}
return 0;
@@ -593,9 +604,9 @@ static int record_check_headers(gnutls_session_t session,
/* Here we check if the advertized version is the one we
* negotiated in the handshake.
*/
inline static int record_check_version(gnutls_session_t session,
gnutls_handshake_description_t htype,
opaque version[2])
inline static int
record_check_version (gnutls_session_t session,
gnutls_handshake_description_t htype, opaque version[2])
{
if (htype == GNUTLS_HANDSHAKE_CLIENT_HELLO)
{
@@ -605,14 +616,14 @@ inline static int record_check_version(gnutls_session_t session,
{
gnutls_assert ();
_gnutls_record_log
("REC[%x]: INVALID VERSION PACKET: (%d) %d.%d\n", session,
htype, version[0], version[1]);
("REC[%x]: INVALID VERSION PACKET: (%d) %d.%d\n", session,
htype, version[0], version[1]);
return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
}
}
else if (htype != GNUTLS_HANDSHAKE_SERVER_HELLO
&& gnutls_protocol_get_version(session)
!= _gnutls_version_get(version[0], version[1]))
&& gnutls_protocol_get_version (session)
!= _gnutls_version_get (version[0], version[1]))
{
/* Reject record packets that have a different version than the
* one negotiated. Note that this version is not protected by any
@@ -620,7 +631,7 @@ inline static int record_check_version(gnutls_session_t session,
*/
gnutls_assert ();
_gnutls_record_log ("REC[%x]: INVALID VERSION PACKET: (%d) %d.%d\n",
session, htype, version[0], version[1]);
session, htype, version[0], version[1]);
return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
}
@@ -631,135 +642,135 @@ inline static int record_check_version(gnutls_session_t session,
/* This function will check if the received record type is
* the one we actually expect.
*/
static int record_check_type(gnutls_session_t session,
content_type_t recv_type,
content_type_t type,
gnutls_handshake_description_t htype,
opaque * data,
int data_size)
static int
record_check_type (gnutls_session_t session,
content_type_t recv_type,
content_type_t type,
gnutls_handshake_description_t htype,
opaque * data, int data_size)
{
int ret;
if ((recv_type == type) && (type == GNUTLS_APPLICATION_DATA || type
== GNUTLS_HANDSHAKE || type == GNUTLS_INNER_APPLICATION))
== GNUTLS_HANDSHAKE
|| type == GNUTLS_INNER_APPLICATION))
{
_gnutls_record_buffer_put(type, session, (void *) data, data_size);
_gnutls_record_buffer_put (type, session, (void *) data, data_size);
}
else
{
switch (recv_type)
{
case GNUTLS_ALERT:
case GNUTLS_ALERT:
_gnutls_record_log
("REC[%x]: Alert[%d|%d] - %s - was received\n", session,
data[0], data[1], gnutls_alert_get_name ((int) data[1]));
_gnutls_record_log
("REC[%x]: Alert[%d|%d] - %s - was received\n", session,
data[0], data[1], gnutls_alert_get_name ((int) data[1]));
session->internals.last_alert = data[1];
session->internals.last_alert_level = data[0];
session->internals.last_alert = data[1];
session->internals.last_alert_level = data[0];
/* if close notify is received and
* the alert is not fatal
*/
if (data[1] == GNUTLS_A_CLOSE_NOTIFY && data[0] != GNUTLS_AL_FATAL)
{
/* If we have been expecting for an alert do
*/
session->internals.read_eof = 1;
return GNUTLS_E_INT_RET_0; /* EOF */
}
else
{
/* if close notify is received and
* the alert is not fatal
*/
if (data[1] == GNUTLS_A_CLOSE_NOTIFY && data[0] != GNUTLS_AL_FATAL)
{
/* If we have been expecting for an alert do
*/
session->internals.read_eof = 1;
return GNUTLS_E_INT_RET_0; /* EOF */
}
else
{
/* if the alert is FATAL or WARNING
* return the apropriate message
*/
gnutls_assert ();
ret = GNUTLS_E_WARNING_ALERT_RECEIVED;
if (data[0] == GNUTLS_AL_FATAL)
{
session_unresumable(session);
session_invalidate(session);
ret = GNUTLS_E_FATAL_ALERT_RECEIVED;
}
/* if the alert is FATAL or WARNING
* return the apropriate message
*/
gnutls_assert ();
ret = GNUTLS_E_WARNING_ALERT_RECEIVED;
if (data[0] == GNUTLS_AL_FATAL)
{
session_unresumable (session);
session_invalidate (session);
ret = GNUTLS_E_FATAL_ALERT_RECEIVED;
}
return ret;
}
break;
return ret;
}
break;
case GNUTLS_CHANGE_CIPHER_SPEC:
/* this packet is now handled in the recv_int()
* function
*/
gnutls_assert ()
;
case GNUTLS_CHANGE_CIPHER_SPEC:
/* this packet is now handled in the recv_int()
* function
*/
gnutls_assert ();
return GNUTLS_E_UNEXPECTED_PACKET;
return GNUTLS_E_UNEXPECTED_PACKET;
case GNUTLS_APPLICATION_DATA:
/* even if data is unexpected put it into the buffer */
if ((ret = _gnutls_record_buffer_put(recv_type, session, (void *) data,
data_size)) < 0)
{
gnutls_assert ();
return ret;
}
case GNUTLS_APPLICATION_DATA:
/* even if data is unexpected put it into the buffer */
if ((ret =
_gnutls_record_buffer_put (recv_type, session, (void *) data,
data_size)) < 0)
{
gnutls_assert ();
return ret;
}
/* the got_application data is only returned
* if expecting client hello (for rehandshake
* reasons). Otherwise it is an unexpected packet
*/
if (type == GNUTLS_ALERT || (htype == GNUTLS_HANDSHAKE_CLIENT_HELLO
&& type == GNUTLS_HANDSHAKE))
return GNUTLS_E_GOT_APPLICATION_DATA;
else
{
gnutls_assert ();
return GNUTLS_E_UNEXPECTED_PACKET;
}
/* the got_application data is only returned
* if expecting client hello (for rehandshake
* reasons). Otherwise it is an unexpected packet
*/
if (type == GNUTLS_ALERT || (htype == GNUTLS_HANDSHAKE_CLIENT_HELLO
&& type == GNUTLS_HANDSHAKE))
return GNUTLS_E_GOT_APPLICATION_DATA;
else
{
gnutls_assert ();
return GNUTLS_E_UNEXPECTED_PACKET;
}
break;
case GNUTLS_HANDSHAKE:
/* This is legal if HELLO_REQUEST is received - and we are a client.
* If we are a server, a client may initiate a renegotiation at any time.
*/
if (session->security_parameters.entity == GNUTLS_SERVER)
{
gnutls_assert ();
return GNUTLS_E_REHANDSHAKE;
}
break;
case GNUTLS_HANDSHAKE:
/* This is legal if HELLO_REQUEST is received - and we are a client.
* If we are a server, a client may initiate a renegotiation at any time.
*/
if (session->security_parameters.entity == GNUTLS_SERVER)
{
gnutls_assert ();
return GNUTLS_E_REHANDSHAKE;
}
/* If we are already in a handshake then a Hello
* Request is illegal. But here we don't really care
* since this message will never make it up here.
*/
/* If we are already in a handshake then a Hello
* Request is illegal. But here we don't really care
* since this message will never make it up here.
*/
/* So we accept it */
return _gnutls_recv_hello_request(session, data, data_size);
/* So we accept it */
return _gnutls_recv_hello_request (session, data, data_size);
break;
case GNUTLS_INNER_APPLICATION:
/* even if data is unexpected put it into the buffer */
if ((ret = _gnutls_record_buffer_put(recv_type, session, (void *) data,
data_size)) < 0)
{
gnutls_assert ();
return ret;
}
gnutls_assert ()
;
return GNUTLS_E_UNEXPECTED_PACKET;
break;
default:
break;
case GNUTLS_INNER_APPLICATION:
/* even if data is unexpected put it into the buffer */
if ((ret =
_gnutls_record_buffer_put (recv_type, session, (void *) data,
data_size)) < 0)
{
gnutls_assert ();
return ret;
}
gnutls_assert ();
return GNUTLS_E_UNEXPECTED_PACKET;
break;
default:
_gnutls_record_log
("REC[%x]: Received Unknown packet %d expecting %d\n",
session, recv_type, type);
_gnutls_record_log
("REC[%x]: Received Unknown packet %d expecting %d\n",
session, recv_type, type);
gnutls_assert ()
;
return GNUTLS_E_INTERNAL_ERROR;
gnutls_assert ();
return GNUTLS_E_INTERNAL_ERROR;
}
}
@@ -771,12 +782,12 @@ static int record_check_type(gnutls_session_t session,
* recv buffer. If the buffer was not initialized before it will
* also initialize it.
*/
inline static int get_temp_recv_buffer(gnutls_session_t session,
gnutls_datum_t * tmp)
inline static int
get_temp_recv_buffer (gnutls_session_t session, gnutls_datum_t * tmp)
{
size_t max_record_size;
if (gnutls_compression_get(session) != GNUTLS_COMP_NULL)
if (gnutls_compression_get (session) != GNUTLS_COMP_NULL)
max_record_size = MAX_RECORD_RECV_SIZE + EXTRA_COMP_SIZE;
else
max_record_size = MAX_RECORD_RECV_SIZE;
@@ -793,7 +804,8 @@ inline static int get_temp_recv_buffer(gnutls_session_t session,
/* Initialize the internal buffer.
*/
session->internals.recv_buffer.data
= gnutls_realloc(session->internals.recv_buffer.data, max_record_size);
=
gnutls_realloc (session->internals.recv_buffer.data, max_record_size);
if (session->internals.recv_buffer.data == NULL)
{
@@ -803,7 +815,7 @@ inline static int get_temp_recv_buffer(gnutls_session_t session,
session->internals.recv_buffer.size = max_record_size;
}
tmp->data = session->internals.recv_buffer.data;
tmp->size = session->internals.recv_buffer.size;
@@ -819,11 +831,11 @@ inline static int get_temp_recv_buffer(gnutls_session_t session,
*
* The gnutls_handshake_description_t was introduced to support SSL V2.0 client hellos.
*/
ssize_t _gnutls_recv_int(gnutls_session_t session,
content_type_t type,
gnutls_handshake_description_t htype,
opaque * data,
size_t sizeofdata)
ssize_t
_gnutls_recv_int (gnutls_session_t session,
content_type_t type,
gnutls_handshake_description_t htype,
opaque * data, size_t sizeofdata)
{
gnutls_datum_t tmp;
int decrypted_length;
@@ -842,7 +854,7 @@ ssize_t _gnutls_recv_int(gnutls_session_t session,
return GNUTLS_E_INVALID_REQUEST;
}
begin:
begin:
if (empty_packet > MAX_EMPTY_PACKETS_SEQUENCE)
{
@@ -856,8 +868,8 @@ ssize_t _gnutls_recv_int(gnutls_session_t session,
*/
return 0;
}
else if (session_is_valid(session) != 0 || session->internals.may_not_read
!= 0)
else if (session_is_valid (session) != 0 || session->internals.may_not_read
!= 0)
{
gnutls_assert ();
return GNUTLS_E_INVALID_SESSION;
@@ -866,7 +878,7 @@ ssize_t _gnutls_recv_int(gnutls_session_t session,
/* If we have enough data in the cache do not bother receiving
* a new packet. (in order to flush the cache)
*/
ret = check_buffers(session, type, data, sizeofdata);
ret = check_buffers (session, type, data, sizeofdata);
if (ret != 0)
return ret;
@@ -874,25 +886,25 @@ ssize_t _gnutls_recv_int(gnutls_session_t session,
*/
header_size = RECORD_HEADER_SIZE;
if ((ret = _gnutls_io_read_buffered(session, &headers, header_size, -1))
if ((ret = _gnutls_io_read_buffered (session, &headers, header_size, -1))
!= header_size)
{
if (ret < 0 && gnutls_error_is_fatal(ret) == 0)
if (ret < 0 && gnutls_error_is_fatal (ret) == 0)
return ret;
session_invalidate(session);
session_invalidate (session);
if (type == GNUTLS_ALERT)
{
gnutls_assert ();
return 0; /* we were expecting close notify */
return 0; /* we were expecting close notify */
}
session_unresumable(session);
session_unresumable (session);
gnutls_assert ();
return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
}
if ((ret = record_check_headers(session, headers, type, htype, &recv_type,
version, &length, &header_size)) < 0)
if ((ret = record_check_headers (session, headers, type, htype, &recv_type,
version, &length, &header_size)) < 0)
{
gnutls_assert ();
return ret;
@@ -901,7 +913,7 @@ ssize_t _gnutls_recv_int(gnutls_session_t session,
/* Here we check if the Type of the received packet is
* ok.
*/
if ((ret = check_recv_type(recv_type)) < 0)
if ((ret = check_recv_type (recv_type)) < 0)
{
gnutls_assert ();
return ret;
@@ -910,47 +922,47 @@ ssize_t _gnutls_recv_int(gnutls_session_t session,
/* Here we check if the advertized version is the one we
* negotiated in the handshake.
*/
if ((ret = record_check_version(session, htype, version)) < 0)
if ((ret = record_check_version (session, htype, version)) < 0)
{
gnutls_assert ();
session_invalidate(session);
session_invalidate (session);
return ret;
}
_gnutls_record_log
("REC[%x]: Expected Packet[%d] %s(%d) with length: %d\n", session,
(int) _gnutls_uint64touint32 (&session->connection_state.
read_sequence_number),
_gnutls_packet2str (type), type, sizeofdata);
("REC[%x]: Expected Packet[%d] %s(%d) with length: %d\n", session,
(int) _gnutls_uint64touint32 (&session->connection_state.
read_sequence_number),
_gnutls_packet2str (type), type, sizeofdata);
_gnutls_record_log
("REC[%x]: Received Packet[%d] %s(%d) with length: %d\n", session,
(int) _gnutls_uint64touint32 (&session->connection_state.
read_sequence_number),
_gnutls_packet2str (recv_type), recv_type, length);
("REC[%x]: Received Packet[%d] %s(%d) with length: %d\n", session,
(int) _gnutls_uint64touint32 (&session->connection_state.
read_sequence_number),
_gnutls_packet2str (recv_type), recv_type, length);
if (length > MAX_RECV_SIZE)
{
_gnutls_record_log
("REC[%x]: FATAL ERROR: Received packet with length: %d\n",
session, length);
("REC[%x]: FATAL ERROR: Received packet with length: %d\n",
session, length);
session_unresumable(session);
session_invalidate(session);
session_unresumable (session);
session_invalidate (session);
gnutls_assert ();
return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
}
/* check if we have that data into buffer.
*/
if ((ret = _gnutls_io_read_buffered(session, &recv_data,
header_size + length, recv_type))
if ((ret = _gnutls_io_read_buffered (session, &recv_data,
header_size + length, recv_type))
!= header_size + length)
{
if (ret < 0 && gnutls_error_is_fatal(ret) == 0)
if (ret < 0 && gnutls_error_is_fatal (ret) == 0)
return ret;
session_unresumable(session);
session_invalidate(session);
session_unresumable (session);
session_invalidate (session);
gnutls_assert ();
return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
}
@@ -958,10 +970,10 @@ ssize_t _gnutls_recv_int(gnutls_session_t session,
/* ok now we are sure that we can read all the data - so
* move on !
*/
_gnutls_io_clear_read_buffer(session);
_gnutls_io_clear_read_buffer (session);
ciphertext = &recv_data[header_size];
ret = get_temp_recv_buffer(session, &tmp);
ret = get_temp_recv_buffer (session, &tmp);
if (ret < 0)
{
gnutls_assert ();
@@ -969,12 +981,12 @@ ssize_t _gnutls_recv_int(gnutls_session_t session,
}
/* decrypt the data we got. */
ret = _gnutls_decrypt(session, ciphertext, length, tmp.data, tmp.size,
recv_type);
ret = _gnutls_decrypt (session, ciphertext, length, tmp.data, tmp.size,
recv_type);
if (ret < 0)
{
session_unresumable(session);
session_invalidate(session);
session_unresumable (session);
session_invalidate (session);
gnutls_assert ();
return ret;
}
@@ -987,36 +999,36 @@ ssize_t _gnutls_recv_int(gnutls_session_t session,
{
_gnutls_record_log
("REC[%x]: ChangeCipherSpec Packet was received\n", session);
("REC[%x]: ChangeCipherSpec Packet was received\n", session);
if ((size_t) ret != sizeofdata)
{ /* sizeofdata should be 1 */
{ /* sizeofdata should be 1 */
gnutls_assert ();
return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
}
memcpy(data, tmp.data, sizeofdata);
memcpy (data, tmp.data, sizeofdata);
return ret;
}
_gnutls_record_log
("REC[%x]: Decrypted Packet[%d] %s(%d) with length: %d\n", session,
(int) _gnutls_uint64touint32 (&session->connection_state.
read_sequence_number),
_gnutls_packet2str (recv_type), recv_type, decrypted_length);
("REC[%x]: Decrypted Packet[%d] %s(%d) with length: %d\n", session,
(int) _gnutls_uint64touint32 (&session->connection_state.
read_sequence_number),
_gnutls_packet2str (recv_type), recv_type, decrypted_length);
/* increase sequence number
*/
if (_gnutls_uint64pp(&session->connection_state.read_sequence_number) != 0)
if (_gnutls_uint64pp (&session->connection_state.read_sequence_number) != 0)
{
session_invalidate(session);
session_invalidate (session);
gnutls_assert ();
return GNUTLS_E_RECORD_LIMIT_REACHED;
}
/* check type - this will also invalidate sessions if a fatal alert has been received */
ret = record_check_type(session, recv_type, type, htype, tmp.data,
decrypted_length);
ret = record_check_type (session, recv_type, type, htype, tmp.data,
decrypted_length);
if (ret < 0)
{
if (ret == GNUTLS_E_INT_RET_0)
@@ -1028,10 +1040,11 @@ ssize_t _gnutls_recv_int(gnutls_session_t session,
/* Get Application data from buffer
*/
if ((recv_type == type) && (type == GNUTLS_APPLICATION_DATA || type
== GNUTLS_HANDSHAKE || type == GNUTLS_INNER_APPLICATION))
== GNUTLS_HANDSHAKE
|| type == GNUTLS_INNER_APPLICATION))
{
ret = _gnutls_record_buffer_get(type, session, data, sizeofdata);
ret = _gnutls_record_buffer_get (type, session, data, sizeofdata);
if (ret < 0)
{
gnutls_assert ();
@@ -1040,9 +1053,9 @@ ssize_t _gnutls_recv_int(gnutls_session_t session,
/* if the buffer just got empty
*/
if (_gnutls_record_buffer_get_size(type, session) == 0)
if (_gnutls_record_buffer_get_size (type, session) == 0)
{
if ((ret2 = _gnutls_io_clear_peeked_data(session)) < 0)
if ((ret2 = _gnutls_io_clear_peeked_data (session)) < 0)
{
gnutls_assert ();
return ret2;
@@ -1101,12 +1114,12 @@ ssize_t _gnutls_recv_int(gnutls_session_t session,
* number of bytes this function can send in a single call depends on
* the negotiated maximum record size.
**/
ssize_t gnutls_record_send(gnutls_session_t session,
const void *data,
size_t sizeofdata)
ssize_t
gnutls_record_send (gnutls_session_t session,
const void *data, size_t sizeofdata)
{
return _gnutls_send_int(session, GNUTLS_APPLICATION_DATA, -1, data,
sizeofdata);
return _gnutls_send_int (session, GNUTLS_APPLICATION_DATA, -1, data,
sizeofdata);
}
/**
@@ -1139,12 +1152,11 @@ ssize_t gnutls_record_send(gnutls_session_t session,
* error code is returned in case of an error. The number of bytes
* received might be less than @sizeofdata.
**/
ssize_t gnutls_record_recv(gnutls_session_t session,
void *data,
size_t sizeofdata)
ssize_t
gnutls_record_recv (gnutls_session_t session, void *data, size_t sizeofdata)
{
return _gnutls_recv_int(session, GNUTLS_APPLICATION_DATA, -1, data,
sizeofdata);
return _gnutls_recv_int (session, GNUTLS_APPLICATION_DATA, -1, data,
sizeofdata);
}
/**
@@ -1155,7 +1167,8 @@ ssize_t gnutls_record_recv(gnutls_session_t session,
* connection. The maximum record size is negotiated by the client
* after the first handshake message.
**/
size_t gnutls_record_get_max_size(gnutls_session_t session)
size_t
gnutls_record_get_max_size (gnutls_session_t session)
{
/* Recv will hold the negotiated max record size
* always.
@@ -1180,15 +1193,15 @@ size_t gnutls_record_get_max_size(gnutls_session_t session)
* This function uses a TLS extension called 'max record size'. Not
* all TLS implementations use or even understand this extension.
**/
ssize_t gnutls_record_set_max_size(gnutls_session_t session,
size_t size)
ssize_t
gnutls_record_set_max_size (gnutls_session_t session, size_t size)
{
ssize_t new_size;
if (session->security_parameters.entity == GNUTLS_SERVER)
return GNUTLS_E_INVALID_REQUEST;
new_size = _gnutls_mre_record2num(size);
new_size = _gnutls_mre_record2num (size);
if (new_size < 0)
{
+61 -64
View File
@@ -33,70 +33,68 @@
*
* They should be used only with null terminated strings.
*/
void _gnutls_str_cat(char *dest,
size_t dest_tot_size,
const char *src)
void
_gnutls_str_cat (char *dest, size_t dest_tot_size, const char *src)
{
size_t str_size = strlen(src);
size_t dest_size = strlen(dest);
size_t str_size = strlen (src);
size_t dest_size = strlen (dest);
if (dest_tot_size - dest_size > str_size)
{
strcat(dest, src);
strcat (dest, src);
}
else
{
if (dest_tot_size - dest_size > 0)
{
strncat(dest, src, (dest_tot_size - dest_size) - 1);
strncat (dest, src, (dest_tot_size - dest_size) - 1);
dest[dest_tot_size - 1] = 0;
}
}
}
void _gnutls_str_cpy(char *dest,
size_t dest_tot_size,
const char *src)
void
_gnutls_str_cpy (char *dest, size_t dest_tot_size, const char *src)
{
size_t str_size = strlen(src);
size_t str_size = strlen (src);
if (dest_tot_size > str_size)
{
strcpy(dest, src);
strcpy (dest, src);
}
else
{
if (dest_tot_size > 0)
{
strncpy(dest, src, (dest_tot_size) - 1);
strncpy (dest, src, (dest_tot_size) - 1);
dest[dest_tot_size - 1] = 0;
}
}
}
void _gnutls_mem_cpy(char *dest,
size_t dest_tot_size,
const char *src,
size_t src_size)
void
_gnutls_mem_cpy (char *dest,
size_t dest_tot_size, const char *src, size_t src_size)
{
if (dest_tot_size >= src_size)
{
memcpy(dest, src, src_size);
memcpy (dest, src, src_size);
}
else
{
if (dest_tot_size > 0)
{
memcpy(dest, src, dest_tot_size);
memcpy (dest, src, dest_tot_size);
}
}
}
void _gnutls_string_init(gnutls_string * str,
gnutls_alloc_function alloc_func,
gnutls_realloc_function realloc_func,
gnutls_free_function free_func)
void
_gnutls_string_init (gnutls_string * str,
gnutls_alloc_function alloc_func,
gnutls_realloc_function realloc_func,
gnutls_free_function free_func)
{
str->data = NULL;
str->max_length = 0;
@@ -107,11 +105,12 @@ void _gnutls_string_init(gnutls_string * str,
str->realloc_func = realloc_func;
}
void _gnutls_string_clear(gnutls_string * str)
void
_gnutls_string_clear (gnutls_string * str)
{
if (str == NULL || str->data == NULL)
return;
str->free_func(str->data);
str->free_func (str->data);
str->data = NULL;
str->max_length = 0;
@@ -120,7 +119,8 @@ void _gnutls_string_clear(gnutls_string * str)
/* This one does not copy the string.
*/
gnutls_datum_t _gnutls_string2datum(gnutls_string * str)
gnutls_datum_t
_gnutls_string2datum (gnutls_string * str)
{
gnutls_datum_t ret;
@@ -132,14 +132,14 @@ gnutls_datum_t _gnutls_string2datum(gnutls_string * str)
#define MIN_CHUNK 256
int _gnutls_string_copy_str(gnutls_string * dest,
const char *src)
int
_gnutls_string_copy_str (gnutls_string * dest, const char *src)
{
size_t src_len = strlen(src);
size_t src_len = strlen (src);
size_t max;
if (dest->max_length >= src_len)
{
memcpy(dest->data, src, src_len);
memcpy (dest->data, src, src_len);
dest->length = src_len;
return src_len;
@@ -147,7 +147,7 @@ int _gnutls_string_copy_str(gnutls_string * dest,
else
{
max = (src_len > MIN_CHUNK) ? src_len : MIN_CHUNK;
dest->data = dest->realloc_func(dest->data, max);
dest->data = dest->realloc_func (dest->data, max);
if (dest->data == NULL)
{
gnutls_assert ();
@@ -155,32 +155,32 @@ int _gnutls_string_copy_str(gnutls_string * dest,
}
dest->max_length = MAX (MIN_CHUNK, src_len);
memcpy(dest->data, src, src_len);
memcpy (dest->data, src, src_len);
dest->length = src_len;
return src_len;
}
}
int _gnutls_string_append_str(gnutls_string * dest,
const char *src)
int
_gnutls_string_append_str (gnutls_string * dest, const char *src)
{
size_t src_len = strlen(src);
size_t src_len = strlen (src);
size_t tot_len = src_len + dest->length;
if (dest->max_length >= tot_len)
{
memcpy(&dest->data[dest->length], src, src_len);
memcpy (&dest->data[dest->length], src, src_len);
dest->length = tot_len;
return tot_len;
}
else
{
size_t new_len=
size_t new_len =
MAX (src_len, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK);
dest->data = dest->realloc_func(dest->data, new_len);
dest->data = dest->realloc_func (dest->data, new_len);
if (dest->data == NULL)
{
gnutls_assert ();
@@ -188,32 +188,32 @@ int _gnutls_string_append_str(gnutls_string * dest,
}
dest->max_length = new_len;
memcpy(&dest->data[dest->length], src, src_len);
memcpy (&dest->data[dest->length], src, src_len);
dest->length = tot_len;
return tot_len;
}
}
int _gnutls_string_append_data(gnutls_string * dest,
const void *data,
size_t data_size)
int
_gnutls_string_append_data (gnutls_string * dest,
const void *data, size_t data_size)
{
size_t tot_len = data_size + dest->length;
if (dest->max_length >= tot_len)
{
memcpy(&dest->data[dest->length], data, data_size);
memcpy (&dest->data[dest->length], data, data_size);
dest->length = tot_len;
return tot_len;
}
else
{
size_t new_len=
size_t new_len =
MAX (data_size, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK);
dest->data = dest->realloc_func(dest->data, new_len);
dest->data = dest->realloc_func (dest->data, new_len);
if (dest->data == NULL)
{
gnutls_assert ();
@@ -221,31 +221,30 @@ int _gnutls_string_append_data(gnutls_string * dest,
}
dest->max_length = new_len;
memcpy(&dest->data[dest->length], data, data_size);
memcpy (&dest->data[dest->length], data, data_size);
dest->length = tot_len;
return tot_len;
}
}
int _gnutls_string_append_printf(gnutls_string * dest,
const char *fmt,
...)
int
_gnutls_string_append_printf (gnutls_string * dest, const char *fmt, ...)
{
va_list args;
int len;
char *str;
va_start(args, fmt);
len = vasprintf(&str, fmt, args);
va_end(args);
va_start (args, fmt);
len = vasprintf (&str, fmt, args);
va_end (args);
if (len < 0 || !str)
return -1;
len = _gnutls_string_append_str(dest, str);
len = _gnutls_string_append_str (dest, str);
free(str);
free (str);
return len;
}
@@ -255,17 +254,16 @@ int _gnutls_string_append_printf(gnutls_string * dest,
* If the buffer does not have enough space to hold the string, a
* truncated hex string is returned (always null terminated).
*/
char * _gnutls_bin2hex(const void *_old,
size_t oldlen,
char *buffer,
size_t buffer_size)
char *
_gnutls_bin2hex (const void *_old,
size_t oldlen, char *buffer, size_t buffer_size)
{
unsigned int i, j;
const opaque *old = _old;
for (i = j = 0; i < oldlen && j + 2 < buffer_size; j += 2)
{
sprintf(&buffer[j], "%.2x", old[i]);
sprintf (&buffer[j], "%.2x", old[i]);
i++;
}
buffer[j] = '\0';
@@ -275,10 +273,9 @@ char * _gnutls_bin2hex(const void *_old,
/* just a hex2bin function.
*/
int _gnutls_hex2bin(const opaque * hex_data,
int hex_size,
opaque * bin_data,
size_t * bin_size)
int
_gnutls_hex2bin (const opaque * hex_data,
int hex_size, opaque * bin_data, size_t * bin_size)
{
int i, j;
opaque hex2_data[3];
@@ -299,7 +296,7 @@ int _gnutls_hex2bin(const opaque * hex_data,
hex2_data[0] = hex_data[i];
hex2_data[1] = hex_data[i + 1];
hex2_data[2] = 0;
val = strtoul((char *) hex2_data, NULL, 16);
val = strtoul ((char *) hex2_data, NULL, 16);
if (val == ULONG_MAX)
{
gnutls_assert ();
+1569 -1573
View File
@@ -54,49 +54,49 @@
#define PKCS12_PBE_RC2_40_SHA1_OID "1.2.840.113549.1.12.1.6"
struct pbkdf2_params
{
opaque salt[32];
int salt_size;
unsigned int iter_count;
unsigned int key_size;
};
{
opaque salt[32];
int salt_size;
unsigned int iter_count;
unsigned int key_size;
};
struct pbe_enc_params
{
gnutls_cipher_algorithm_t cipher;
opaque iv[8];
int iv_size;
};
{
gnutls_cipher_algorithm_t cipher;
opaque iv[8];
int iv_size;
};
static int generate_key (schema_id schema, const char *password,
struct pbkdf2_params *kdf_params,
struct pbe_enc_params *enc_params,
gnutls_datum_t * key);
struct pbkdf2_params *kdf_params,
struct pbe_enc_params *enc_params,
gnutls_datum_t * key);
static int read_pbkdf2_params (ASN1_TYPE pbes2_asn,
const gnutls_datum_t * der,
struct pbkdf2_params *params);
const gnutls_datum_t * der,
struct pbkdf2_params *params);
static int read_pbe_enc_params (ASN1_TYPE pbes2_asn,
const gnutls_datum_t * der,
struct pbe_enc_params *params);
const gnutls_datum_t * der,
struct pbe_enc_params *params);
static int decrypt_data (schema_id, ASN1_TYPE pkcs8_asn, const char *root,
const char *password,
const struct pbkdf2_params *kdf_params,
const struct pbe_enc_params *enc_params,
gnutls_datum_t * decrypted_data);
const char *password,
const struct pbkdf2_params *kdf_params,
const struct pbe_enc_params *enc_params,
gnutls_datum_t * decrypted_data);
static int decode_private_key_info (const gnutls_datum_t * der,
gnutls_x509_privkey_t pkey);
gnutls_x509_privkey_t pkey);
static int write_schema_params (schema_id schema, ASN1_TYPE pkcs8_asn,
const char *where,
const struct pbkdf2_params *kdf_params,
const struct pbe_enc_params *enc_params);
const char *where,
const struct pbkdf2_params *kdf_params,
const struct pbe_enc_params *enc_params);
static int encrypt_data (const gnutls_datum_t * plain,
const struct pbe_enc_params *enc_params,
gnutls_datum_t * key, gnutls_datum_t * encrypted);
const struct pbe_enc_params *enc_params,
gnutls_datum_t * key, gnutls_datum_t * encrypted);
static int read_pkcs12_kdf_params (ASN1_TYPE pbes2_asn,
struct pbkdf2_params *params);
struct pbkdf2_params *params);
static int write_pkcs12_kdf_params (ASN1_TYPE pbes2_asn,
const struct pbkdf2_params *params);
const struct pbkdf2_params *params);
#define PEM_PKCS8 "ENCRYPTED PRIVATE KEY"
#define PEM_UNENCRYPTED_PKCS8 "PRIVATE KEY"
@@ -106,24 +106,24 @@ static int write_pkcs12_kdf_params (ASN1_TYPE pbes2_asn,
*/
inline static int
check_schema (const char *oid)
{
{
if (strcmp (oid, PBES2_OID) == 0)
if (strcmp (oid, PBES2_OID) == 0)
return PBES2;
if (strcmp (oid, PKCS12_PBE_3DES_SHA1_OID) == 0)
if (strcmp (oid, PKCS12_PBE_3DES_SHA1_OID) == 0)
return PKCS12_3DES_SHA1;
if (strcmp (oid, PKCS12_PBE_ARCFOUR_SHA1_OID) == 0)
if (strcmp (oid, PKCS12_PBE_ARCFOUR_SHA1_OID) == 0)
return PKCS12_ARCFOUR_SHA1;
if (strcmp (oid, PKCS12_PBE_RC2_40_SHA1_OID) == 0)
if (strcmp (oid, PKCS12_PBE_RC2_40_SHA1_OID) == 0)
return PKCS12_RC2_40_SHA1;
_gnutls_x509_log ("PKCS encryption schema OID '%s' is unsupported.\n", oid);
_gnutls_x509_log ("PKCS encryption schema OID '%s' is unsupported.\n", oid);
return GNUTLS_E_UNKNOWN_CIPHER_TYPE;
}
return GNUTLS_E_UNKNOWN_CIPHER_TYPE;
}
/* Encodes a private key to the raw format PKCS #8 needs.
* For RSA it is a PKCS #1 DER private key and for DSA it is
@@ -131,324 +131,320 @@ check_schema (const char *oid)
*/
inline static int
_encode_privkey (gnutls_x509_privkey pkey, gnutls_datum * raw)
{
size_t size = 0;
opaque *data = NULL;
int ret;
ASN1_TYPE spk = ASN1_TYPE_EMPTY;
{
size_t size = 0;
opaque *data = NULL;
int ret;
ASN1_TYPE spk = ASN1_TYPE_EMPTY;
switch (pkey->pk_algorithm)
{
case GNUTLS_PK_RSA:
ret =
switch (pkey->pk_algorithm)
{
case GNUTLS_PK_RSA:
ret =
gnutls_x509_privkey_export (pkey, GNUTLS_X509_FMT_DER, NULL, &size);
if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
{
gnutls_assert ();
goto error;
}
if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
{
gnutls_assert ();
goto error;
}
data = gnutls_malloc (size);
if (data == NULL)
{
gnutls_assert ();
ret = GNUTLS_E_MEMORY_ERROR;
goto error;
}
data = gnutls_malloc (size);
if (data == NULL)
{
gnutls_assert ();
ret = GNUTLS_E_MEMORY_ERROR;
goto error;
}
ret =
ret =
gnutls_x509_privkey_export (pkey, GNUTLS_X509_FMT_DER, data, &size);
if (ret < 0)
{
gnutls_assert ();
goto error;
}
if (ret < 0)
{
gnutls_assert ();
goto error;
}
raw->data = data;
raw->size = size;
break;
default:
gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
raw->data = data;
raw->size = size;
break;
default:
gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
return 0;
return 0;
error:
gnutls_free (data);
asn1_delete_structure (&spk);
return ret;
error:
gnutls_free (data);
asn1_delete_structure (&spk);
return ret;
}
}
/*
/*
* 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;
opaque null = 0;
const char *oid;
gnutls_datum algo_params =
{ NULL, 0};
gnutls_datum algo_privkey =
{ NULL, 0};
gnutls_datum_t * der, ASN1_TYPE * pkey_info)
{
int result, len;
opaque null = 0;
const char *oid;
gnutls_datum algo_params = { NULL, 0 };
gnutls_datum algo_privkey = { NULL, 0 };
if (pkey->pk_algorithm == GNUTLS_PK_RSA)
{
oid = PK_PKIX1_RSA_OID;
/* parameters are null
*/
}
else
{
oid = PK_DSA_OID;
result =
if (pkey->pk_algorithm == GNUTLS_PK_RSA)
{
oid = PK_PKIX1_RSA_OID;
/* parameters are null
*/
}
else
{
oid = PK_DSA_OID;
result =
_gnutls_x509_write_dsa_params (pkey->params, pkey->params_size,
&algo_params);
if (result < 0)
{
gnutls_assert ();
return result;
}
}
&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;
}
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 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 =
/* 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;
}
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
result =
result =
asn1_write_value (*pkey_info, "privateKeyAlgorithm.parameters",
algo_params.data, algo_params.size);
_gnutls_free_datum (&algo_params);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
algo_params.data, algo_params.size);
_gnutls_free_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;
}
/* Write the raw private key
*/
result = _encode_privkey (pkey, &algo_privkey);
if (result < 0)
{
gnutls_assert ();
goto error;
}
result =
result =
asn1_write_value (*pkey_info, "privateKey", algo_privkey.data,
algo_privkey.size);
_gnutls_free_datum (&algo_privkey);
algo_privkey.size);
_gnutls_free_datum (&algo_privkey);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
/* 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;
}
/* 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;
}
/* 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;
}
/* 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;
}
result = asn1_der_coding (*pkey_info, "", der->data, &len, NULL);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
return 0;
return 0;
error:
asn1_delete_structure (pkey_info);
_gnutls_free_datum (&algo_params);
_gnutls_free_datum (&algo_privkey);
return result;
error:
asn1_delete_structure (pkey_info);
_gnutls_free_datum (&algo_params);
_gnutls_free_datum (&algo_privkey);
return result;
}
}
/* 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 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;
if ((result =
asn1_create_element (_gnutls_get_pkix (),
"PKIX1.pkcs-8-EncryptedPrivateKeyInfo",
&pkcs8_asn)) != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
if ((result =
asn1_create_element (_gnutls_get_pkix (),
"PKIX1.pkcs-8-EncryptedPrivateKeyInfo",
&pkcs8_asn)) != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
/* Write the encryption schema OID
*/
switch (schema)
{
case PBES2:
result =
/* Write the encryption schema OID
*/
switch (schema)
{
case PBES2:
result =
asn1_write_value (pkcs8_asn, "encryptionAlgorithm.algorithm",
PBES2_OID, 1);
break;
case PKCS12_3DES_SHA1:
result =
PBES2_OID, 1);
break;
case PKCS12_3DES_SHA1:
result =
asn1_write_value (pkcs8_asn, "encryptionAlgorithm.algorithm",
PKCS12_PBE_3DES_SHA1_OID, 1);
break;
case PKCS12_ARCFOUR_SHA1:
result =
PKCS12_PBE_3DES_SHA1_OID, 1);
break;
case PKCS12_ARCFOUR_SHA1:
result =
asn1_write_value (pkcs8_asn, "encryptionAlgorithm.algorithm",
PKCS12_PBE_ARCFOUR_SHA1_OID, 1);
break;
case PKCS12_RC2_40_SHA1:
result =
PKCS12_PBE_ARCFOUR_SHA1_OID, 1);
break;
case PKCS12_RC2_40_SHA1:
result =
asn1_write_value (pkcs8_asn, "encryptionAlgorithm.algorithm",
PKCS12_PBE_RC2_40_SHA1_OID, 1);
break;
PKCS12_PBE_RC2_40_SHA1_OID, 1);
break;
}
}
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
/* Generate a symmetric key.
*/
/* Generate a symmetric key.
*/
result = generate_key (schema, password, &kdf_params, &enc_params, &key);
if (result < 0)
{
gnutls_assert ();
goto error;
}
result = generate_key (schema, password, &kdf_params, &enc_params, &key);
if (result < 0)
{
gnutls_assert ();
goto error;
}
result =
result =
write_schema_params (schema, pkcs8_asn,
"encryptionAlgorithm.parameters", &kdf_params,
&enc_params);
if (result < 0)
{
gnutls_assert ();
goto error;
}
"encryptionAlgorithm.parameters", &kdf_params,
&enc_params);
if (result < 0)
{
gnutls_assert ();
goto error;
}
/* Parameters have been encoded. Now
* encrypt the Data.
*/
result = encrypt_data (der_key, &enc_params, &key, &tmp);
if (result < 0)
{
gnutls_assert ();
goto error;
}
/* Parameters have been encoded. Now
* encrypt the Data.
*/
result = 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;
}
/* 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_datum (&key);
_gnutls_free_datum (&tmp);
_gnutls_free_datum (&key);
*out = pkcs8_asn;
*out = pkcs8_asn;
return 0;
return 0;
error:
_gnutls_free_datum (&key);
_gnutls_free_datum (&tmp);
asn1_delete_structure (&pkcs8_asn);
return result;
}
error:
_gnutls_free_datum (&key);
_gnutls_free_datum (&tmp);
asn1_delete_structure (&pkcs8_asn);
return result;
}
/**
* gnutls_x509_privkey_export_pkcs8 - This function will export the private key to PKCS8 format
* @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.
* @password: the password that will be used to encrypt the key.
* @flags: an ORed sequence of gnutls_pkcs_encrypt_flags_t
* @output_data: will contain a private key PEM or DER encoded
* @output_data_size: holds the size of output_data (and will be
@@ -456,7 +452,7 @@ encode_to_pkcs8_key (schema_id schema, const gnutls_datum_t * der_key,
*
* 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
* 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
@@ -476,215 +472,215 @@ encode_to_pkcs8_key (schema_id schema, const gnutls_datum_t * der_key,
**/
int
gnutls_x509_privkey_export_pkcs8 (gnutls_x509_privkey_t key,
gnutls_x509_crt_fmt_t format,
const char *password,
unsigned int flags,
void *output_data,
size_t * output_data_size)
{
ASN1_TYPE pkcs8_asn, pkey_info;
int ret;
gnutls_datum_t tmp;
schema_id schema;
gnutls_x509_crt_fmt_t format,
const char *password,
unsigned int flags,
void *output_data,
size_t * output_data_size)
{
ASN1_TYPE pkcs8_asn, pkey_info;
int ret;
gnutls_datum_t tmp;
schema_id schema;
if (key == NULL)
{
gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
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;
}
/* 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;
}
if (flags & GNUTLS_PKCS_USE_PKCS12_3DES)
if (flags & GNUTLS_PKCS_USE_PKCS12_3DES)
schema = PKCS12_3DES_SHA1;
else if (flags & GNUTLS_PKCS_USE_PKCS12_ARCFOUR)
else if (flags & GNUTLS_PKCS_USE_PKCS12_ARCFOUR)
schema = PKCS12_ARCFOUR_SHA1;
else if (flags & GNUTLS_PKCS_USE_PKCS12_RC2_40)
else if (flags & GNUTLS_PKCS_USE_PKCS12_RC2_40)
schema = PKCS12_RC2_40_SHA1;
else
else
schema = PBES2;
if ((flags & GNUTLS_PKCS_PLAIN) || password == NULL)
{
_gnutls_free_datum (&tmp);
if ((flags & GNUTLS_PKCS_PLAIN) || password == NULL)
{
_gnutls_free_datum (&tmp);
ret =
ret =
_gnutls_x509_export_int (pkey_info, format,
PEM_UNENCRYPTED_PKCS8,
output_data, output_data_size);
PEM_UNENCRYPTED_PKCS8,
output_data, output_data_size);
asn1_delete_structure (&pkey_info);
}
else
{
asn1_delete_structure (&pkey_info); /* we don't need it */
asn1_delete_structure (&pkey_info);
}
else
{
asn1_delete_structure (&pkey_info); /* we don't need it */
ret = encode_to_pkcs8_key (schema, &tmp, password, &pkcs8_asn);
_gnutls_free_datum (&tmp);
ret = encode_to_pkcs8_key (schema, &tmp, password, &pkcs8_asn);
_gnutls_free_datum (&tmp);
if (ret < 0)
{
gnutls_assert ();
return ret;
}
if (ret < 0)
{
gnutls_assert ();
return ret;
}
ret =
ret =
_gnutls_x509_export_int (pkcs8_asn, format, PEM_PKCS8,
output_data, output_data_size);
output_data, output_data_size);
asn1_delete_structure (&pkcs8_asn);
}
asn1_delete_structure (&pkcs8_asn);
}
return ret;
}
return ret;
}
/* Read the parameters cipher, IV, salt etc using the given
* schema ID.
*/
static 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;
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)
{
switch (schema)
{
case PBES2:
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;
}
/* 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;
}
/* 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;
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_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;
}
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;
asn1_delete_structure (&pbes2_asn);
return 0;
break;
case PKCS12_3DES_SHA1:
case PKCS12_ARCFOUR_SHA1:
case PKCS12_RC2_40_SHA1:
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 ((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;
}
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;
}
/* 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;
}
result = read_pkcs12_kdf_params (pbes2_asn, kdf_params);
if (result < 0)
{
gnutls_assert ();
goto error;
}
if (enc_params->iv_size)
{
result =
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;
}
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);
asn1_delete_structure (&pbes2_asn);
return 0;
break;
return 0;
break;
} /* switch */
} /* switch */
return GNUTLS_E_UNKNOWN_CIPHER_TYPE;
return GNUTLS_E_UNKNOWN_CIPHER_TYPE;
error:
asn1_delete_structure (&pbes2_asn);
return result;
}
error:
asn1_delete_structure (&pbes2_asn);
return result;
}
/* Converts a PKCS #8 key to
* an internal structure (gnutls_private_key)
@@ -692,157 +688,157 @@ read_pkcs_schema_params (schema_id schema, const char *password,
*/
static int
decode_pkcs8_key (const gnutls_datum_t * raw_key,
const char *password, gnutls_x509_privkey_t pkey)
{
int result, len;
char enc_oid[64];
gnutls_datum_t tmp;
ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY, pkcs8_asn = ASN1_TYPE_EMPTY;
int params_start, params_end, params_len;
struct pbkdf2_params kdf_params;
struct pbe_enc_params enc_params;
schema_id schema;
const char *password, gnutls_x509_privkey_t pkey)
{
int result, len;
char enc_oid[64];
gnutls_datum_t tmp;
ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY, pkcs8_asn = ASN1_TYPE_EMPTY;
int params_start, params_end, params_len;
struct pbkdf2_params kdf_params;
struct pbe_enc_params enc_params;
schema_id schema;
if ((result =
asn1_create_element (_gnutls_get_pkix (),
"PKIX1.pkcs-8-EncryptedPrivateKeyInfo",
&pkcs8_asn)) != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
if ((result =
asn1_create_element (_gnutls_get_pkix (),
"PKIX1.pkcs-8-EncryptedPrivateKeyInfo",
&pkcs8_asn)) != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
result = asn1_der_decoding (&pkcs8_asn, raw_key->data, raw_key->size, NULL);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
result = asn1_der_decoding (&pkcs8_asn, raw_key->data, raw_key->size, NULL);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
/* Check the encryption schema OID
*/
len = sizeof (enc_oid);
result =
/* 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;
}
enc_oid, &len);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
goto error;
}
if ((result = check_schema (enc_oid)) < 0)
{
gnutls_assert ();
goto error;
}
if ((result = check_schema (enc_oid)) < 0)
{
gnutls_assert ();
goto error;
}
schema = result;
schema = result;
/* Get the DER encoding of the parameters.
*/
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;
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 =
result =
read_pkcs_schema_params (schema, password,
&raw_key->data[params_start],
params_len, &kdf_params, &enc_params);
&raw_key->data[params_start],
params_len, &kdf_params, &enc_params);
/* Parameters have been decoded. Now
* decrypt the EncryptedData.
*/
result =
/* Parameters have been decoded. Now
* decrypt the EncryptedData.
*/
result =
decrypt_data (schema, pkcs8_asn, "encryptedData", password,
&kdf_params, &enc_params, &tmp);
if (result < 0)
{
gnutls_assert ();
goto error;
}
&kdf_params, &enc_params, &tmp);
if (result < 0)
{
gnutls_assert ();
goto error;
}
asn1_delete_structure (&pkcs8_asn);
asn1_delete_structure (&pkcs8_asn);
result = decode_private_key_info (&tmp, pkey);
_gnutls_free_datum (&tmp);
result = decode_private_key_info (&tmp, pkey);
_gnutls_free_datum (&tmp);
if (result < 0)
{
/* We've gotten this far. In the real world it's almost certain
* that we're dealing with a good file, but wrong password.
* Sadly like 90% of random data is somehow valid DER for the
* a first small number of bytes, so no easy way to guarantee. */
if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND ||
result == GNUTLS_E_ASN1_IDENTIFIER_NOT_FOUND ||
result == GNUTLS_E_ASN1_DER_ERROR ||
result == GNUTLS_E_ASN1_VALUE_NOT_FOUND ||
result == GNUTLS_E_ASN1_GENERIC_ERROR ||
result == GNUTLS_E_ASN1_VALUE_NOT_VALID ||
result == GNUTLS_E_ASN1_TAG_ERROR ||
result == GNUTLS_E_ASN1_TAG_IMPLICIT ||
result == GNUTLS_E_ASN1_TYPE_ANY_ERROR ||
result == GNUTLS_E_ASN1_SYNTAX_ERROR ||
result == GNUTLS_E_ASN1_DER_OVERFLOW)
{
result = GNUTLS_E_DECRYPTION_FAILED;
}
if (result < 0)
{
/* We've gotten this far. In the real world it's almost certain
* that we're dealing with a good file, but wrong password.
* Sadly like 90% of random data is somehow valid DER for the
* a first small number of bytes, so no easy way to guarantee. */
if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND ||
result == GNUTLS_E_ASN1_IDENTIFIER_NOT_FOUND ||
result == GNUTLS_E_ASN1_DER_ERROR ||
result == GNUTLS_E_ASN1_VALUE_NOT_FOUND ||
result == GNUTLS_E_ASN1_GENERIC_ERROR ||
result == GNUTLS_E_ASN1_VALUE_NOT_VALID ||
result == GNUTLS_E_ASN1_TAG_ERROR ||
result == GNUTLS_E_ASN1_TAG_IMPLICIT ||
result == GNUTLS_E_ASN1_TYPE_ANY_ERROR ||
result == GNUTLS_E_ASN1_SYNTAX_ERROR ||
result == GNUTLS_E_ASN1_DER_OVERFLOW)
{
result = GNUTLS_E_DECRYPTION_FAILED;
}
gnutls_assert ();
goto error;
}
gnutls_assert ();
goto error;
}
return 0;
return 0;
error:
asn1_delete_structure (&pbes2_asn);
asn1_delete_structure (&pkcs8_asn);
return result;
}
error:
asn1_delete_structure (&pbes2_asn);
asn1_delete_structure (&pkcs8_asn);
return result;
}
/* Decodes an RSA privateKey from a PKCS8 structure.
*/
static int
_decode_pkcs8_rsa_key (ASN1_TYPE pkcs8_asn, gnutls_x509_privkey pkey)
{
int ret;
gnutls_datum tmp;
{
int ret;
gnutls_datum tmp;
ret = _gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp, 0);
if (ret < 0)
{
gnutls_assert ();
goto error;
}
ret = _gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp, 0);
if (ret < 0)
{
gnutls_assert ();
goto error;
}
pkey->key = _gnutls_privkey_decode_pkcs1_rsa_key (&tmp, pkey);
_gnutls_free_datum (&tmp);
if (pkey->key == NULL)
{
gnutls_assert ();
goto error;
}
pkey->key = _gnutls_privkey_decode_pkcs1_rsa_key (&tmp, pkey);
_gnutls_free_datum (&tmp);
if (pkey->key == NULL)
{
gnutls_assert ();
goto error;
}
return 0;
return 0;
error:
gnutls_x509_privkey_deinit (pkey);
return ret;
}
error:
gnutls_x509_privkey_deinit (pkey);
return ret;
}
/* TODO rm if unsed - we will probable support only RSA certificates */
/* Decodes an DSA privateKey and params from a PKCS8 structure.
*/
static int
_decode_pkcs8_dsa_key (ASN1_TYPE pkcs8_asn, gnutls_x509_privkey pkey)
{
@@ -882,7 +878,7 @@ _decode_pkcs8_dsa_key (ASN1_TYPE pkcs8_asn, gnutls_x509_privkey pkey)
goto error;
}
/* the public key can be generated as g^x mod p */
the public key can be generated as g^x mod p
pkey->params[3] = _gnutls_mpi_alloc_like (pkey->params[0]);
if (pkey->params[3] == NULL)
{
@@ -911,77 +907,78 @@ _decode_pkcs8_dsa_key (ASN1_TYPE pkcs8_asn, gnutls_x509_privkey pkey)
gnutls_x509_privkey_deinit (pkey);
return ret;
}
*/
static int
decode_private_key_info (const gnutls_datum_t * der,
gnutls_x509_privkey_t pkey)
{
int result, len;
opaque oid[64];
ASN1_TYPE pkcs8_asn = ASN1_TYPE_EMPTY;
gnutls_x509_privkey_t pkey)
{
int result, len;
opaque oid[64];
ASN1_TYPE pkcs8_asn = ASN1_TYPE_EMPTY;
if ((result =
asn1_create_element (_gnutls_get_pkix (),
"PKIX1.pkcs-8-PrivateKeyInfo",
&pkcs8_asn)) != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
if ((result =
asn1_create_element (_gnutls_get_pkix (),
"PKIX1.pkcs-8-PrivateKeyInfo",
&pkcs8_asn)) != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
result = asn1_der_decoding (&pkcs8_asn, der->data, der->size, NULL);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
result = asn1_der_decoding (&pkcs8_asn, der->data, der->size, NULL);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
/* Check the private key algorithm OID
*/
len = sizeof (oid);
result =
/* Check the private key algorithm OID
*/
len = sizeof (oid);
result =
asn1_read_value (pkcs8_asn, "privateKeyAlgorithm.algorithm", oid, &len);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
/* we only support RSA and DSA private keys.
*/
if (strcmp (oid, PK_PKIX1_RSA_OID) == 0)
/* we only support RSA and DSA private keys.
*/
if (strcmp (oid, PK_PKIX1_RSA_OID) == 0)
pkey->pk_algorithm = GNUTLS_PK_RSA;
else
{
gnutls_assert ();
_gnutls_x509_log
else
{
gnutls_assert ();
_gnutls_x509_log
("PKCS #8 private key OID '%s' is unsupported.\n", oid);
result = GNUTLS_E_UNKNOWN_PK_ALGORITHM;
goto error;
}
result = GNUTLS_E_UNKNOWN_PK_ALGORITHM;
goto error;
}
/* Get the DER encoding of the actual private key.
*/
/* Get the DER encoding of the actual private key.
*/
if (pkey->pk_algorithm == GNUTLS_PK_RSA)
if (pkey->pk_algorithm == GNUTLS_PK_RSA)
result = _decode_pkcs8_rsa_key (pkcs8_asn, pkey);
if (result < 0)
{
gnutls_assert ();
return result;
}
if (result < 0)
{
gnutls_assert ();
return result;
}
result = 0;
result = 0;
error:
asn1_delete_structure (&pkcs8_asn);
error:
asn1_delete_structure (&pkcs8_asn);
return result;
return result;
}
}
/**
* gnutls_x509_privkey_import_pkcs8 - This function will import a DER or PEM PKCS8 encoded key
@@ -1008,1212 +1005,1211 @@ decode_private_key_info (const gnutls_datum_t * der,
**/
int
gnutls_x509_privkey_import_pkcs8 (gnutls_x509_privkey_t key,
const gnutls_datum_t * data,
gnutls_x509_crt_fmt_t format,
const char *password, unsigned int flags)
{
int result = 0, need_free = 0;
gnutls_datum_t _data;
const gnutls_datum_t * data,
gnutls_x509_crt_fmt_t format,
const char *password, unsigned int flags)
{
int result = 0, need_free = 0;
gnutls_datum_t _data;
if (key == NULL)
{
gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
if (key == NULL)
{
gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
_data.data = data->data;
_data.size = data->size;
_data.data = data->data;
_data.size = data->size;
key->pk_algorithm = GNUTLS_PK_UNKNOWN;
key->pk_algorithm = GNUTLS_PK_UNKNOWN;
/* If the Certificate is in PEM format then decode it
*/
if (format == GNUTLS_X509_FMT_PEM)
{
opaque *out;
/* If the Certificate is in PEM format then decode it
*/
if (format == GNUTLS_X509_FMT_PEM)
{
opaque *out;
/* Try the first header
*/
result =
/* Try the first header
*/
result =
_gnutls_fbase64_decode (PEM_UNENCRYPTED_PKCS8,
data->data, data->size, &out);
data->data, data->size, &out);
if (result < 0)
{ /* Try the encrypted header
*/
result =
if (result < 0)
{ /* Try the encrypted header
*/
result =
_gnutls_fbase64_decode (PEM_PKCS8, data->data, data->size, &out);
if (result <= 0)
{
if (result == 0)
if (result <= 0)
{
if (result == 0)
result = GNUTLS_E_INTERNAL_ERROR;
gnutls_assert ();
return result;
}
}
else if (flags == 0)
gnutls_assert ();
return result;
}
}
else if (flags == 0)
flags |= GNUTLS_PKCS_PLAIN;
_data.data = out;
_data.size = result;
_data.data = out;
_data.size = result;
need_free = 1;
}
need_free = 1;
}
if (flags & GNUTLS_PKCS_PLAIN)
{
result = decode_private_key_info (&_data, key);
}
else
{ /* encrypted. */
result = decode_pkcs8_key (&_data, password, key);
}
if (flags & GNUTLS_PKCS_PLAIN)
{
result = decode_private_key_info (&_data, key);
}
else
{ /* encrypted. */
result = decode_pkcs8_key (&_data, password, key);
}
if (result < 0)
{
gnutls_assert ();
goto cleanup;
}
if (result < 0)
{
gnutls_assert ();
goto cleanup;
}
if (need_free)
if (need_free)
_gnutls_free_datum (&_data);
/* The key has now been decoded.
*/
/* The key has now been decoded.
*/
return 0;
return 0;
cleanup:
key->pk_algorithm = GNUTLS_PK_UNKNOWN;
if (need_free)
cleanup:
key->pk_algorithm = GNUTLS_PK_UNKNOWN;
if (need_free)
_gnutls_free_datum (&_data);
return result;
}
return result;
}
/* Reads the PBKDF2 parameters.
*/
static int
read_pbkdf2_params (ASN1_TYPE pbes2_asn,
const gnutls_datum_t * der, struct pbkdf2_params *params)
{
int params_start, params_end;
int params_len, len, result;
ASN1_TYPE pbkdf2_asn = ASN1_TYPE_EMPTY;
char oid[64];
const gnutls_datum_t * der, struct pbkdf2_params *params)
{
int params_start, params_end;
int params_len, len, result;
ASN1_TYPE pbkdf2_asn = ASN1_TYPE_EMPTY;
char oid[64];
memset (params, 0, sizeof (params));
memset (params, 0, sizeof (params));
/* Check the key derivation algorithm
*/
len = sizeof (oid);
result =
/* Check the key derivation algorithm
*/
len = sizeof (oid);
result =
asn1_read_value (pbes2_asn, "keyDerivationFunc.algorithm", oid, &len);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
return _gnutls_asn2err (result);
}
_gnutls_hard_log ("keyDerivationFunc.algorithm: %s\n", oid);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
return _gnutls_asn2err (result);
}
_gnutls_hard_log ("keyDerivationFunc.algorithm: %s\n", oid);
if (strcmp (oid, PBKDF2_OID) != 0)
{
gnutls_assert ();
_gnutls_x509_log
if (strcmp (oid, PBKDF2_OID) != 0)
{
gnutls_assert ();
_gnutls_x509_log
("PKCS #8 key derivation OID '%s' is unsupported.\n", oid);
return _gnutls_asn2err (result);
}
return _gnutls_asn2err (result);
}
result =
result =
asn1_der_decoding_startEnd (pbes2_asn, der->data, der->size,
"keyDerivationFunc.parameters",
&params_start, &params_end);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
return _gnutls_asn2err (result);
}
params_len = params_end - params_start + 1;
"keyDerivationFunc.parameters",
&params_start, &params_end);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
return _gnutls_asn2err (result);
}
params_len = params_end - params_start + 1;
/* Now check the key derivation and the encryption
* functions.
*/
if ((result =
asn1_create_element (_gnutls_get_pkix (),
"PKIX1.pkcs-5-PBKDF2-params",
&pbkdf2_asn)) != ASN1_SUCCESS)
{
gnutls_assert ();
return _gnutls_asn2err (result);
}
/* Now check the key derivation and the encryption
* functions.
*/
if ((result =
asn1_create_element (_gnutls_get_pkix (),
"PKIX1.pkcs-5-PBKDF2-params",
&pbkdf2_asn)) != ASN1_SUCCESS)
{
gnutls_assert ();
return _gnutls_asn2err (result);
}
result =
result =
asn1_der_decoding (&pbkdf2_asn, &der->data[params_start],
params_len, NULL);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
params_len, NULL);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
/* read the salt */
params->salt_size = sizeof (params->salt);
result =
/* read the salt */
params->salt_size = sizeof (params->salt);
result =
asn1_read_value (pbkdf2_asn, "salt.specified", params->salt,
&params->salt_size);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
_gnutls_hard_log ("salt.specified.size: %d\n", params->salt_size);
&params->salt_size);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
_gnutls_hard_log ("salt.specified.size: %d\n", params->salt_size);
/* read the iteration count
*/
result =
/* read the iteration count
*/
result =
_gnutls_x509_read_uint (pbkdf2_asn, "iterationCount",
&params->iter_count);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
goto error;
}
_gnutls_hard_log ("iterationCount: %d\n", params->iter_count);
&params->iter_count);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
goto error;
}
_gnutls_hard_log ("iterationCount: %d\n", params->iter_count);
/* read the keylength, if it is set.
*/
result =
/* read the keylength, if it is set.
*/
result =
_gnutls_x509_read_uint (pbkdf2_asn, "keyLength", &params->key_size);
if (result < 0)
{
params->key_size = 0;
}
_gnutls_hard_log ("keyLength: %d\n", params->key_size);
if (result < 0)
{
params->key_size = 0;
}
_gnutls_hard_log ("keyLength: %d\n", params->key_size);
/* We don't read the PRF. We only use the default.
*/
/* We don't read the PRF. We only use the default.
*/
return 0;
return 0;
error:
asn1_delete_structure (&pbkdf2_asn);
return result;
error:
asn1_delete_structure (&pbkdf2_asn);
return result;
}
}
/* Reads the PBE parameters from PKCS-12 schemas (*&#%*&#% RSA).
*/
static int
read_pkcs12_kdf_params (ASN1_TYPE pbes2_asn, struct pbkdf2_params *params)
{
int result;
{
int result;
memset (params, 0, sizeof (params));
memset (params, 0, sizeof (params));
/* read the salt */
params->salt_size = sizeof (params->salt);
result =
/* read the salt */
params->salt_size = sizeof (params->salt);
result =
asn1_read_value (pbes2_asn, "salt", params->salt, &params->salt_size);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
_gnutls_hard_log ("salt.size: %d\n", params->salt_size);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
_gnutls_hard_log ("salt.size: %d\n", params->salt_size);
/* read the iteration count
*/
result =
/* read the iteration count
*/
result =
_gnutls_x509_read_uint (pbes2_asn, "iterations", &params->iter_count);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
goto error;
}
_gnutls_hard_log ("iterationCount: %d\n", params->iter_count);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
goto error;
}
_gnutls_hard_log ("iterationCount: %d\n", params->iter_count);
params->key_size = 0;
params->key_size = 0;
return 0;
return 0;
error:
return result;
error:
return result;
}
}
/* Writes the PBE parameters for PKCS-12 schemas.
*/
static int
write_pkcs12_kdf_params (ASN1_TYPE pbes2_asn,
const struct pbkdf2_params *kdf_params)
{
int result;
const struct pbkdf2_params *kdf_params)
{
int result;
/* write the salt
*/
result =
/* write the salt
*/
result =
asn1_write_value (pbes2_asn, "salt",
kdf_params->salt, kdf_params->salt_size);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
_gnutls_hard_log ("salt.size: %d\n", kdf_params->salt_size);
kdf_params->salt, kdf_params->salt_size);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
_gnutls_hard_log ("salt.size: %d\n", kdf_params->salt_size);
/* write the iteration count
*/
result =
/* write the iteration count
*/
result =
_gnutls_x509_write_uint32 (pbes2_asn, "iterations",
kdf_params->iter_count);
if (result < 0)
{
gnutls_assert ();
goto error;
}
_gnutls_hard_log ("iterationCount: %d\n", kdf_params->iter_count);
kdf_params->iter_count);
if (result < 0)
{
gnutls_assert ();
goto error;
}
_gnutls_hard_log ("iterationCount: %d\n", kdf_params->iter_count);
return 0;
return 0;
error:
return result;
error:
return result;
}
}
/* Converts an OID to a gnutls cipher type.
*/
inline static int
oid2cipher (const char *oid, gnutls_cipher_algorithm_t * algo)
{
{
*algo = 0;
*algo = 0;
if (strcmp (oid, DES_EDE3_CBC_OID) == 0)
{
*algo = GNUTLS_CIPHER_3DES_CBC;
return 0;
}
if (strcmp (oid, DES_EDE3_CBC_OID) == 0)
{
*algo = GNUTLS_CIPHER_3DES_CBC;
return 0;
}
if (strcmp (oid, DES_CBC_OID) == 0)
{
*algo = GNUTLS_CIPHER_DES_CBC;
return 0;
}
if (strcmp (oid, DES_CBC_OID) == 0)
{
*algo = GNUTLS_CIPHER_DES_CBC;
return 0;
}
_gnutls_x509_log ("PKCS #8 encryption OID '%s' is unsupported.\n", oid);
return GNUTLS_E_UNKNOWN_CIPHER_TYPE;
}
_gnutls_x509_log ("PKCS #8 encryption OID '%s' is unsupported.\n", oid);
return GNUTLS_E_UNKNOWN_CIPHER_TYPE;
}
static int
read_pbe_enc_params (ASN1_TYPE pbes2_asn,
const gnutls_datum_t * der,
struct pbe_enc_params *params)
{
int params_start, params_end;
int params_len, len, result;
ASN1_TYPE pbe_asn = ASN1_TYPE_EMPTY;
char oid[64];
const gnutls_datum_t * der,
struct pbe_enc_params *params)
{
int params_start, params_end;
int params_len, len, result;
ASN1_TYPE pbe_asn = ASN1_TYPE_EMPTY;
char oid[64];
memset (params, 0, sizeof (params));
memset (params, 0, sizeof (params));
/* Check the encryption algorithm
*/
len = sizeof (oid);
result =
/* Check the encryption algorithm
*/
len = sizeof (oid);
result =
asn1_read_value (pbes2_asn, "encryptionScheme.algorithm", oid, &len);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
goto error;
}
_gnutls_hard_log ("encryptionScheme.algorithm: %s\n", oid);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
goto error;
}
_gnutls_hard_log ("encryptionScheme.algorithm: %s\n", oid);
if ((result = oid2cipher (oid, &params->cipher)) < 0)
{
gnutls_assert ();
goto error;
}
if ((result = oid2cipher (oid, &params->cipher)) < 0)
{
gnutls_assert ();
goto error;
}
result =
result =
asn1_der_decoding_startEnd (pbes2_asn, der->data, der->size,
"encryptionScheme.parameters",
&params_start, &params_end);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
return _gnutls_asn2err (result);
}
params_len = params_end - params_start + 1;
"encryptionScheme.parameters",
&params_start, &params_end);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
return _gnutls_asn2err (result);
}
params_len = params_end - params_start + 1;
/* Now check the encryption parameters.
*/
if ((result =
asn1_create_element (_gnutls_get_pkix (),
"PKIX1.pkcs-5-des-EDE3-CBC-params",
&pbe_asn)) != ASN1_SUCCESS)
{
gnutls_assert ();
return _gnutls_asn2err (result);
}
/* Now check the encryption parameters.
*/
if ((result =
asn1_create_element (_gnutls_get_pkix (),
"PKIX1.pkcs-5-des-EDE3-CBC-params",
&pbe_asn)) != ASN1_SUCCESS)
{
gnutls_assert ();
return _gnutls_asn2err (result);
}
result =
result =
asn1_der_decoding (&pbe_asn, &der->data[params_start], params_len, NULL);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
/* read the IV */
params->iv_size = sizeof (params->iv);
result = asn1_read_value (pbe_asn, "", params->iv, &params->iv_size);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
_gnutls_hard_log ("IV.size: %d\n", params->iv_size);
/* read the IV */
params->iv_size = sizeof (params->iv);
result = asn1_read_value (pbe_asn, "", params->iv, &params->iv_size);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
_gnutls_hard_log ("IV.size: %d\n", params->iv_size);
return 0;
return 0;
error:
asn1_delete_structure (&pbe_asn);
return result;
error:
asn1_delete_structure (&pbe_asn);
return result;
}
}
static int
decrypt_data (schema_id schema, ASN1_TYPE pkcs8_asn,
const char *root, const char *password,
const struct pbkdf2_params *kdf_params,
const struct pbe_enc_params *enc_params,
gnutls_datum_t * decrypted_data)
{
int result;
int data_size;
opaque *data = NULL, *key = NULL;
gnutls_datum_t dkey, d_iv;
cipher_hd_t ch = NULL;
int key_size;
const char *root, const char *password,
const struct pbkdf2_params *kdf_params,
const struct pbe_enc_params *enc_params,
gnutls_datum_t * decrypted_data)
{
int result;
int data_size;
opaque *data = NULL, *key = NULL;
gnutls_datum_t dkey, d_iv;
cipher_hd_t ch = NULL;
int key_size;
data_size = 0;
result = asn1_read_value (pkcs8_asn, root, NULL, &data_size);
if (result != ASN1_MEM_ERROR)
{
gnutls_assert ();
return _gnutls_asn2err (result);
}
data_size = 0;
result = asn1_read_value (pkcs8_asn, root, NULL, &data_size);
if (result != ASN1_MEM_ERROR)
{
gnutls_assert ();
return _gnutls_asn2err (result);
}
data = gnutls_malloc (data_size);
if (data == NULL)
{
gnutls_assert ();
return GNUTLS_E_MEMORY_ERROR;
}
data = gnutls_malloc (data_size);
if (data == NULL)
{
gnutls_assert ();
return GNUTLS_E_MEMORY_ERROR;
}
result = asn1_read_value (pkcs8_asn, root, data, &data_size);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
result = asn1_read_value (pkcs8_asn, root, data, &data_size);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
if (kdf_params->key_size == 0)
{
key_size = gnutls_cipher_get_key_size (enc_params->cipher);
}
else
if (kdf_params->key_size == 0)
{
key_size = gnutls_cipher_get_key_size (enc_params->cipher);
}
else
key_size = kdf_params->key_size;
key = gnutls_alloca (key_size);
if (key == NULL)
{
gnutls_assert ();
result = GNUTLS_E_MEMORY_ERROR;
goto error;
}
key = gnutls_alloca (key_size);
if (key == NULL)
{
gnutls_assert ();
result = GNUTLS_E_MEMORY_ERROR;
goto error;
}
/* generate the key
*/
if (schema == PBES2)
{
result = gc_pbkdf2_sha1 (password, strlen (password),
kdf_params->salt, kdf_params->salt_size,
kdf_params->iter_count, key, key_size);
/* generate the key
*/
if (schema == PBES2)
{
result = gc_pbkdf2_sha1 (password, strlen (password),
kdf_params->salt, kdf_params->salt_size,
kdf_params->iter_count, key, key_size);
if (result != GC_OK)
{
gnutls_assert ();
result = GNUTLS_E_DECRYPTION_FAILED;
goto error;
}
}
else
{
result =
if (result != GC_OK)
{
gnutls_assert ();
result = GNUTLS_E_DECRYPTION_FAILED;
goto error;
}
}
else
{
result =
_pkcs12_string_to_key (1 /*KEY*/, kdf_params->salt,
kdf_params->salt_size,
kdf_params->iter_count, password,
key_size, key);
kdf_params->salt_size,
kdf_params->iter_count, password,
key_size, key);
if (result < 0)
{
gnutls_assert ();
goto error;
}
}
if (result < 0)
{
gnutls_assert ();
goto error;
}
}
/* do the decryption.
*/
dkey.data = key;
dkey.size = key_size;
/* do the decryption.
*/
dkey.data = key;
dkey.size = key_size;
d_iv.data = (opaque *) enc_params->iv;
d_iv.size = enc_params->iv_size;
ch = _gnutls_cipher_init (enc_params->cipher, &dkey, &d_iv);
d_iv.data = (opaque *) enc_params->iv;
d_iv.size = enc_params->iv_size;
ch = _gnutls_cipher_init (enc_params->cipher, &dkey, &d_iv);
gnutls_afree (key);
key = NULL;
gnutls_afree (key);
key = NULL;
if (ch == NULL)
{
gnutls_assert ();
result = GNUTLS_E_DECRYPTION_FAILED;
goto error;
}
if (ch == NULL)
{
gnutls_assert ();
result = GNUTLS_E_DECRYPTION_FAILED;
goto error;
}
result = _gnutls_cipher_decrypt (ch, data, data_size);
if (result < 0)
{
gnutls_assert ();
goto error;
}
result = _gnutls_cipher_decrypt (ch, data, data_size);
if (result < 0)
{
gnutls_assert ();
goto error;
}
decrypted_data->data = data;
decrypted_data->data = data;
if (_gnutls_cipher_get_block_size (enc_params->cipher) != 1)
if (_gnutls_cipher_get_block_size (enc_params->cipher) != 1)
decrypted_data->size = data_size - data[data_size - 1];
else
else
decrypted_data->size = data_size;
_gnutls_cipher_deinit (ch);
_gnutls_cipher_deinit (ch);
return 0;
return 0;
error:
gnutls_free (data);
gnutls_afree (key);
if (ch != NULL)
error:
gnutls_free (data);
gnutls_afree (key);
if (ch != NULL)
_gnutls_cipher_deinit (ch);
return result;
}
return result;
}
/* Writes the PBKDF2 parameters.
*/
static int
write_pbkdf2_params (ASN1_TYPE pbes2_asn,
const struct pbkdf2_params *kdf_params)
{
int result;
ASN1_TYPE pbkdf2_asn = ASN1_TYPE_EMPTY;
opaque tmp[64];
const struct pbkdf2_params *kdf_params)
{
int result;
ASN1_TYPE pbkdf2_asn = ASN1_TYPE_EMPTY;
opaque tmp[64];
/* Write the key derivation algorithm
*/
result =
/* Write the key derivation algorithm
*/
result =
asn1_write_value (pbes2_asn, "keyDerivationFunc.algorithm",
PBKDF2_OID, 1);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
return _gnutls_asn2err (result);
}
PBKDF2_OID, 1);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
return _gnutls_asn2err (result);
}
/* Now write the key derivation and the encryption
* functions.
*/
if ((result =
asn1_create_element (_gnutls_get_pkix (),
"PKIX1.pkcs-5-PBKDF2-params",
&pbkdf2_asn)) != ASN1_SUCCESS)
{
gnutls_assert ();
return _gnutls_asn2err (result);
}
/* Now write the key derivation and the encryption
* functions.
*/
if ((result =
asn1_create_element (_gnutls_get_pkix (),
"PKIX1.pkcs-5-PBKDF2-params",
&pbkdf2_asn)) != ASN1_SUCCESS)
{
gnutls_assert ();
return _gnutls_asn2err (result);
}
result = asn1_write_value (pbkdf2_asn, "salt", "specified", 1);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
result = asn1_write_value (pbkdf2_asn, "salt", "specified", 1);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
/* write the salt
*/
result =
/* write the salt
*/
result =
asn1_write_value (pbkdf2_asn, "salt.specified",
kdf_params->salt, kdf_params->salt_size);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
_gnutls_hard_log ("salt.specified.size: %d\n", kdf_params->salt_size);
kdf_params->salt, kdf_params->salt_size);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
_gnutls_hard_log ("salt.specified.size: %d\n", kdf_params->salt_size);
/* write the iteration count
*/
_gnutls_write_uint32 (kdf_params->iter_count, tmp);
/* write the iteration count
*/
_gnutls_write_uint32 (kdf_params->iter_count, tmp);
result = asn1_write_value (pbkdf2_asn, "iterationCount", tmp, 4);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
_gnutls_hard_log ("iterationCount: %d\n", kdf_params->iter_count);
result = asn1_write_value (pbkdf2_asn, "iterationCount", tmp, 4);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
_gnutls_hard_log ("iterationCount: %d\n", kdf_params->iter_count);
/* write the keylength, if it is set.
*/
result = asn1_write_value (pbkdf2_asn, "keyLength", NULL, 0);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
/* write the keylength, if it is set.
*/
result = asn1_write_value (pbkdf2_asn, "keyLength", NULL, 0);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
/* We write an emptry prf.
*/
result = asn1_write_value (pbkdf2_asn, "prf", NULL, 0);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
/* We write an emptry prf.
*/
result = asn1_write_value (pbkdf2_asn, "prf", NULL, 0);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
/* now encode them an put the DER output
* in the keyDerivationFunc.parameters
*/
result = _gnutls_x509_der_encode_and_copy (pbkdf2_asn, "",
pbes2_asn,
"keyDerivationFunc.parameters",
0);
if (result < 0)
{
gnutls_assert ();
goto error;
}
/* now encode them an put the DER output
* in the keyDerivationFunc.parameters
*/
result = _gnutls_x509_der_encode_and_copy (pbkdf2_asn, "",
pbes2_asn,
"keyDerivationFunc.parameters",
0);
if (result < 0)
{
gnutls_assert ();
goto error;
}
return 0;
return 0;
error:
asn1_delete_structure (&pbkdf2_asn);
return result;
error:
asn1_delete_structure (&pbkdf2_asn);
return result;
}
}
static int
write_pbe_enc_params (ASN1_TYPE pbes2_asn,
const struct pbe_enc_params *params)
{
int result;
ASN1_TYPE pbe_asn = ASN1_TYPE_EMPTY;
const struct pbe_enc_params *params)
{
int result;
ASN1_TYPE pbe_asn = ASN1_TYPE_EMPTY;
/* Write the encryption algorithm
*/
result =
/* Write the encryption algorithm
*/
result =
asn1_write_value (pbes2_asn, "encryptionScheme.algorithm",
DES_EDE3_CBC_OID, 1);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
goto error;
}
_gnutls_hard_log ("encryptionScheme.algorithm: %s\n", DES_EDE3_CBC_OID);
DES_EDE3_CBC_OID, 1);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
goto error;
}
_gnutls_hard_log ("encryptionScheme.algorithm: %s\n", DES_EDE3_CBC_OID);
/* Now check the encryption parameters.
*/
if ((result =
asn1_create_element (_gnutls_get_pkix (),
"PKIX1.pkcs-5-des-EDE3-CBC-params",
&pbe_asn)) != ASN1_SUCCESS)
{
gnutls_assert ();
return _gnutls_asn2err (result);
}
/* Now check the encryption parameters.
*/
if ((result =
asn1_create_element (_gnutls_get_pkix (),
"PKIX1.pkcs-5-des-EDE3-CBC-params",
&pbe_asn)) != ASN1_SUCCESS)
{
gnutls_assert ();
return _gnutls_asn2err (result);
}
/* read the salt */
result = asn1_write_value (pbe_asn, "", params->iv, params->iv_size);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
_gnutls_hard_log ("IV.size: %d\n", params->iv_size);
/* read the salt */
result = asn1_write_value (pbe_asn, "", params->iv, params->iv_size);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
_gnutls_hard_log ("IV.size: %d\n", params->iv_size);
/* now encode them an put the DER output
* in the encryptionScheme.parameters
*/
result = _gnutls_x509_der_encode_and_copy (pbe_asn, "",
pbes2_asn,
"encryptionScheme.parameters",
0);
if (result < 0)
{
gnutls_assert ();
goto error;
}
/* now encode them an put the DER output
* in the encryptionScheme.parameters
*/
result = _gnutls_x509_der_encode_and_copy (pbe_asn, "",
pbes2_asn,
"encryptionScheme.parameters",
0);
if (result < 0)
{
gnutls_assert ();
goto error;
}
return 0;
return 0;
error:
asn1_delete_structure (&pbe_asn);
return result;
error:
asn1_delete_structure (&pbe_asn);
return result;
}
}
/* Generates a key and also stores the key parameters.
*/
static int
generate_key (schema_id schema,
const char *password,
struct pbkdf2_params *kdf_params,
struct pbe_enc_params *enc_params, gnutls_datum_t * key)
{
opaque rnd[2];
int ret;
const char *password,
struct pbkdf2_params *kdf_params,
struct pbe_enc_params *enc_params, gnutls_datum_t * key)
{
opaque rnd[2];
int ret;
/* We should use the flags here to use different
* encryption algorithms etc.
*/
/* We should use the flags here to use different
* encryption algorithms etc.
*/
if (schema == PKCS12_ARCFOUR_SHA1)
if (schema == PKCS12_ARCFOUR_SHA1)
enc_params->cipher = GNUTLS_CIPHER_ARCFOUR_128;
else if (schema == PKCS12_3DES_SHA1)
else if (schema == PKCS12_3DES_SHA1)
enc_params->cipher = GNUTLS_CIPHER_3DES_CBC;
else if (schema == PKCS12_RC2_40_SHA1)
else if (schema == PKCS12_RC2_40_SHA1)
enc_params->cipher = GNUTLS_CIPHER_RC2_40_CBC;
if (gc_pseudo_random (rnd, 2) != GC_OK)
{
gnutls_assert ();
return GNUTLS_E_RANDOM_FAILED;
}
if (gc_pseudo_random (rnd, 2) != GC_OK)
{
gnutls_assert ();
return GNUTLS_E_RANDOM_FAILED;
}
/* generate salt */
/* generate salt */
if (schema == PBES2)
{
kdf_params->salt_size = MIN (sizeof (kdf_params->salt), (unsigned) (10 + (rnd[1] % 10)));
}
else
if (schema == PBES2)
{
kdf_params->salt_size =
MIN (sizeof (kdf_params->salt), (unsigned) (10 + (rnd[1] % 10)));
}
else
kdf_params->salt_size = 8;
if (gc_pseudo_random (kdf_params->salt, kdf_params->salt_size) != GC_OK)
{
gnutls_assert ();
return GNUTLS_E_RANDOM_FAILED;
}
if (gc_pseudo_random (kdf_params->salt, kdf_params->salt_size) != GC_OK)
{
gnutls_assert ();
return GNUTLS_E_RANDOM_FAILED;
}
kdf_params->iter_count = 256 + rnd[0];
key->size = kdf_params->key_size =
kdf_params->iter_count = 256 + rnd[0];
key->size = kdf_params->key_size =
gnutls_cipher_get_key_size (enc_params->cipher);
enc_params->iv_size = _gnutls_cipher_get_iv_size (enc_params->cipher);
enc_params->iv_size = _gnutls_cipher_get_iv_size (enc_params->cipher);
key->data = gnutls_secure_malloc (key->size);
if (key->data == NULL)
{
gnutls_assert ();
return GNUTLS_E_MEMORY_ERROR;
}
key->data = gnutls_secure_malloc (key->size);
if (key->data == NULL)
{
gnutls_assert ();
return GNUTLS_E_MEMORY_ERROR;
}
/* now generate the key.
*/
/* now generate the key.
*/
if (schema == PBES2)
{
if (schema == PBES2)
{
ret = gc_pbkdf2_sha1 (password, strlen (password),
kdf_params->salt, kdf_params->salt_size,
kdf_params->iter_count,
key->data, kdf_params->key_size);
if (ret != GC_OK)
{
gnutls_assert ();
return GNUTLS_E_ENCRYPTION_FAILED;
}
ret = gc_pbkdf2_sha1 (password, strlen (password),
kdf_params->salt, kdf_params->salt_size,
kdf_params->iter_count,
key->data, kdf_params->key_size);
if (ret != GC_OK)
{
gnutls_assert ();
return GNUTLS_E_ENCRYPTION_FAILED;
}
if (enc_params->iv_size &&
gc_nonce (enc_params->iv, enc_params->iv_size) != GC_OK)
{
gnutls_assert ();
return GNUTLS_E_RANDOM_FAILED;
}
}
else
{ /* PKCS12 schemas */
ret =
if (enc_params->iv_size &&
gc_nonce (enc_params->iv, enc_params->iv_size) != GC_OK)
{
gnutls_assert ();
return GNUTLS_E_RANDOM_FAILED;
}
}
else
{ /* PKCS12 schemas */
ret =
_pkcs12_string_to_key (1 /*KEY*/, kdf_params->salt,
kdf_params->salt_size,
kdf_params->iter_count, password,
kdf_params->key_size, key->data);
if (ret < 0)
{
gnutls_assert ();
return ret;
}
kdf_params->salt_size,
kdf_params->iter_count, password,
kdf_params->key_size, key->data);
if (ret < 0)
{
gnutls_assert ();
return ret;
}
/* Now generate the IV
*/
if (enc_params->iv_size)
{
ret =
/* Now generate the IV
*/
if (enc_params->iv_size)
{
ret =
_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 (ret < 0)
{
gnutls_assert ();
return ret;
}
}
}
kdf_params->salt_size,
kdf_params->iter_count, password,
enc_params->iv_size, enc_params->iv);
if (ret < 0)
{
gnutls_assert ();
return ret;
}
}
}
return 0;
}
return 0;
}
/* Encodes the parameters to be written in the encryptionAlgorithm.parameters
* part.
*/
static int
write_schema_params (schema_id schema, ASN1_TYPE pkcs8_asn,
const char *where,
const struct pbkdf2_params *kdf_params,
const struct pbe_enc_params *enc_params)
{
int result;
ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY;
const char *where,
const struct pbkdf2_params *kdf_params,
const struct pbe_enc_params *enc_params)
{
int result;
ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY;
if (schema == PBES2)
{
if ((result =
asn1_create_element (_gnutls_get_pkix (),
"PKIX1.pkcs-5-PBES2-params",
&pbes2_asn)) != ASN1_SUCCESS)
{
gnutls_assert ();
return _gnutls_asn2err (result);
}
if (schema == PBES2)
{
if ((result =
asn1_create_element (_gnutls_get_pkix (),
"PKIX1.pkcs-5-PBES2-params",
&pbes2_asn)) != ASN1_SUCCESS)
{
gnutls_assert ();
return _gnutls_asn2err (result);
}
result = write_pbkdf2_params (pbes2_asn, kdf_params);
if (result < 0)
{
gnutls_assert ();
goto error;
}
result = write_pbkdf2_params (pbes2_asn, kdf_params);
if (result < 0)
{
gnutls_assert ();
goto error;
}
result = write_pbe_enc_params (pbes2_asn, enc_params);
if (result < 0)
{
gnutls_assert ();
goto error;
}
result = write_pbe_enc_params (pbes2_asn, enc_params);
if (result < 0)
{
gnutls_assert ();
goto error;
}
result = _gnutls_x509_der_encode_and_copy (pbes2_asn, "",
pkcs8_asn, where, 0);
if (result < 0)
{
gnutls_assert ();
goto error;
}
result = _gnutls_x509_der_encode_and_copy (pbes2_asn, "",
pkcs8_asn, where, 0);
if (result < 0)
{
gnutls_assert ();
goto error;
}
asn1_delete_structure (&pbes2_asn);
}
else
{ /* PKCS12 schemas */
asn1_delete_structure (&pbes2_asn);
}
else
{ /* PKCS12 schemas */
if ((result =
asn1_create_element (_gnutls_get_pkix (),
"PKIX1.pkcs-12-PbeParams",
&pbes2_asn)) != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
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 = write_pkcs12_kdf_params (pbes2_asn, kdf_params);
if (result < 0)
{
gnutls_assert ();
goto error;
}
result = write_pkcs12_kdf_params (pbes2_asn, kdf_params);
if (result < 0)
{
gnutls_assert ();
goto error;
}
result = _gnutls_x509_der_encode_and_copy (pbes2_asn, "",
pkcs8_asn, where, 0);
if (result < 0)
{
gnutls_assert ();
goto error;
}
result = _gnutls_x509_der_encode_and_copy (pbes2_asn, "",
pkcs8_asn, where, 0);
if (result < 0)
{
gnutls_assert ();
goto error;
}
asn1_delete_structure (&pbes2_asn);
asn1_delete_structure (&pbes2_asn);
}
}
return 0;
return 0;
error:
asn1_delete_structure (&pbes2_asn);
return result;
error:
asn1_delete_structure (&pbes2_asn);
return result;
}
}
static int
encrypt_data (const gnutls_datum_t * plain,
const struct pbe_enc_params *enc_params,
gnutls_datum_t * key, gnutls_datum_t * encrypted)
{
int result;
int data_size;
opaque *data = NULL;
gnutls_datum_t d_iv;
cipher_hd_t ch = NULL;
opaque pad, pad_size;
const struct pbe_enc_params *enc_params,
gnutls_datum_t * key, gnutls_datum_t * encrypted)
{
int result;
int data_size;
opaque *data = NULL;
gnutls_datum_t d_iv;
cipher_hd_t ch = NULL;
opaque pad, pad_size;
pad_size = _gnutls_cipher_get_block_size (enc_params->cipher);
pad_size = _gnutls_cipher_get_block_size (enc_params->cipher);
if (pad_size == 1) /* stream */
if (pad_size == 1) /* stream */
pad_size = 0;
data = gnutls_malloc (plain->size + pad_size);
if (data == NULL)
{
gnutls_assert ();
return GNUTLS_E_MEMORY_ERROR;
}
data = gnutls_malloc (plain->size + pad_size);
if (data == NULL)
{
gnutls_assert ();
return GNUTLS_E_MEMORY_ERROR;
}
memcpy (data, plain->data, plain->size);
memcpy (data, plain->data, plain->size);
if (pad_size> 0)
{
pad = pad_size - (plain->size % pad_size);
if (pad == 0)
if (pad_size > 0)
{
pad = pad_size - (plain->size % pad_size);
if (pad == 0)
pad = pad_size;
memset (&data[plain->size], pad, pad);
}
else
memset (&data[plain->size], pad, pad);
}
else
pad = 0;
data_size = plain->size + pad;
data_size = plain->size + pad;
d_iv.data = (opaque *) enc_params->iv;
d_iv.size = enc_params->iv_size;
ch = _gnutls_cipher_init (enc_params->cipher, key, &d_iv);
d_iv.data = (opaque *) enc_params->iv;
d_iv.size = enc_params->iv_size;
ch = _gnutls_cipher_init (enc_params->cipher, key, &d_iv);
if (ch == GNUTLS_CIPHER_FAILED)
{
gnutls_assert ();
result = GNUTLS_E_ENCRYPTION_FAILED;
goto error;
}
if (ch == GNUTLS_CIPHER_FAILED)
{
gnutls_assert ();
result = GNUTLS_E_ENCRYPTION_FAILED;
goto error;
}
result = _gnutls_cipher_encrypt (ch, data, data_size);
if (result < 0)
{
gnutls_assert ();
goto error;
}
result = _gnutls_cipher_encrypt (ch, data, data_size);
if (result < 0)
{
gnutls_assert ();
goto error;
}
encrypted->data = data;
encrypted->size = data_size;
encrypted->data = data;
encrypted->size = data_size;
_gnutls_cipher_deinit (ch);
return 0;
error:
gnutls_free (data);
if (ch != NULL)
_gnutls_cipher_deinit (ch);
return 0;
error:
gnutls_free (data);
if (ch != NULL)
_gnutls_cipher_deinit (ch);
return result;
}
return result;
}
/* Decrypts a PKCS #7 encryptedData. The output is allocated
* and stored in dec.
*/
int
_gnutls_pkcs7_decrypt_data (const gnutls_datum_t * data,
const char *password, gnutls_datum_t * dec)
{
int result, len;
char enc_oid[64];
gnutls_datum_t tmp;
ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY, pkcs7_asn = ASN1_TYPE_EMPTY;
int params_start, params_end, params_len;
struct pbkdf2_params kdf_params;
struct pbe_enc_params enc_params;
schema_id schema;
const char *password, gnutls_datum_t * dec)
{
int result, len;
char enc_oid[64];
gnutls_datum_t tmp;
ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY, pkcs7_asn = ASN1_TYPE_EMPTY;
int params_start, params_end, params_len;
struct pbkdf2_params kdf_params;
struct pbe_enc_params enc_params;
schema_id schema;
if ((result =
asn1_create_element (_gnutls_get_pkix (),
"PKIX1.pkcs-7-EncryptedData",
&pkcs7_asn)) != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
if ((result =
asn1_create_element (_gnutls_get_pkix (),
"PKIX1.pkcs-7-EncryptedData",
&pkcs7_asn)) != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
result = asn1_der_decoding (&pkcs7_asn, data->data, data->size, NULL);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
result = asn1_der_decoding (&pkcs7_asn, data->data, data->size, NULL);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
/* Check the encryption schema OID
*/
len = sizeof (enc_oid);
result =
/* Check the encryption schema OID
*/
len = sizeof (enc_oid);
result =
asn1_read_value (pkcs7_asn,
"encryptedContentInfo.contentEncryptionAlgorithm.algorithm",
enc_oid, &len);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
"encryptedContentInfo.contentEncryptionAlgorithm.algorithm",
enc_oid, &len);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
if ((result = check_schema (enc_oid)) < 0)
{
gnutls_assert ();
goto error;
}
schema = result;
if ((result = check_schema (enc_oid)) < 0)
{
gnutls_assert ();
goto error;
}
schema = result;
/* Get the DER encoding of the parameters.
*/
result =
/* Get the DER encoding of the parameters.
*/
result =
asn1_der_decoding_startEnd (pkcs7_asn, data->data, data->size,
"encryptedContentInfo.contentEncryptionAlgorithm.parameters",
&params_start, &params_end);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
params_len = params_end - params_start + 1;
"encryptedContentInfo.contentEncryptionAlgorithm.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 =
result =
read_pkcs_schema_params (schema, password,
&data->data[params_start],
params_len, &kdf_params, &enc_params);
if (result < ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
&data->data[params_start],
params_len, &kdf_params, &enc_params);
if (result < ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
/* Parameters have been decoded. Now
* decrypt the EncryptedData.
*/
/* Parameters have been decoded. Now
* decrypt the EncryptedData.
*/
result =
result =
decrypt_data (schema, pkcs7_asn,
"encryptedContentInfo.encryptedContent", password,
&kdf_params, &enc_params, &tmp);
if (result < 0)
{
gnutls_assert ();
goto error;
}
"encryptedContentInfo.encryptedContent", password,
&kdf_params, &enc_params, &tmp);
if (result < 0)
{
gnutls_assert ();
goto error;
}
asn1_delete_structure (&pkcs7_asn);
asn1_delete_structure (&pkcs7_asn);
*dec = tmp;
*dec = tmp;
return 0;
return 0;
error:
asn1_delete_structure (&pbes2_asn);
asn1_delete_structure (&pkcs7_asn);
return result;
}
error:
asn1_delete_structure (&pbes2_asn);
asn1_delete_structure (&pkcs7_asn);
return result;
}
/* Encrypts to a PKCS #7 encryptedData. The output is allocated
* and stored in enc.
*/
int
_gnutls_pkcs7_encrypt_data (schema_id schema,
const gnutls_datum_t * data,
const char *password, gnutls_datum_t * enc)
{
int result;
gnutls_datum_t key =
{ NULL, 0};
gnutls_datum_t tmp =
{ NULL, 0};
ASN1_TYPE pkcs7_asn = ASN1_TYPE_EMPTY;
struct pbkdf2_params kdf_params;
struct pbe_enc_params enc_params;
const gnutls_datum_t * data,
const char *password, gnutls_datum_t * enc)
{
int result;
gnutls_datum_t key = { NULL, 0 };
gnutls_datum_t tmp = { NULL, 0 };
ASN1_TYPE pkcs7_asn = ASN1_TYPE_EMPTY;
struct pbkdf2_params kdf_params;
struct pbe_enc_params enc_params;
if ((result =
asn1_create_element (_gnutls_get_pkix (),
"PKIX1.pkcs-7-EncryptedData",
&pkcs7_asn)) != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
if ((result =
asn1_create_element (_gnutls_get_pkix (),
"PKIX1.pkcs-7-EncryptedData",
&pkcs7_asn)) != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
/* Write the encryption schema OID
*/
switch (schema)
{
case PBES2:
result =
/* Write the encryption schema OID
*/
switch (schema)
{
case PBES2:
result =
asn1_write_value (pkcs7_asn,
"encryptedContentInfo.contentEncryptionAlgorithm.algorithm",
PBES2_OID, 1);
break;
case PKCS12_3DES_SHA1:
result =
"encryptedContentInfo.contentEncryptionAlgorithm.algorithm",
PBES2_OID, 1);
break;
case PKCS12_3DES_SHA1:
result =
asn1_write_value (pkcs7_asn,
"encryptedContentInfo.contentEncryptionAlgorithm.algorithm",
PKCS12_PBE_3DES_SHA1_OID, 1);
break;
case PKCS12_ARCFOUR_SHA1:
result =
"encryptedContentInfo.contentEncryptionAlgorithm.algorithm",
PKCS12_PBE_3DES_SHA1_OID, 1);
break;
case PKCS12_ARCFOUR_SHA1:
result =
asn1_write_value (pkcs7_asn,
"encryptedContentInfo.contentEncryptionAlgorithm.algorithm",
PKCS12_PBE_ARCFOUR_SHA1_OID, 1);
break;
case PKCS12_RC2_40_SHA1:
result =
"encryptedContentInfo.contentEncryptionAlgorithm.algorithm",
PKCS12_PBE_ARCFOUR_SHA1_OID, 1);
break;
case PKCS12_RC2_40_SHA1:
result =
asn1_write_value (pkcs7_asn,
"encryptedContentInfo.contentEncryptionAlgorithm.algorithm",
PKCS12_PBE_RC2_40_SHA1_OID, 1);
break;
"encryptedContentInfo.contentEncryptionAlgorithm.algorithm",
PKCS12_PBE_RC2_40_SHA1_OID, 1);
break;
}
}
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
/* Generate a symmetric key.
*/
/* Generate a symmetric key.
*/
result = generate_key (schema, password, &kdf_params, &enc_params, &key);
if (result < 0)
{
gnutls_assert ();
goto error;
}
result = generate_key (schema, password, &kdf_params, &enc_params, &key);
if (result < 0)
{
gnutls_assert ();
goto error;
}
result = write_schema_params (schema, pkcs7_asn,
"encryptedContentInfo.contentEncryptionAlgorithm.parameters",
&kdf_params, &enc_params);
if (result < 0)
{
gnutls_assert ();
goto error;
}
result = write_schema_params (schema, pkcs7_asn,
"encryptedContentInfo.contentEncryptionAlgorithm.parameters",
&kdf_params, &enc_params);
if (result < 0)
{
gnutls_assert ();
goto error;
}
/* Parameters have been encoded. Now
* encrypt the Data.
*/
result = encrypt_data (data, &enc_params, &key, &tmp);
if (result < 0)
{
gnutls_assert ();
goto error;
}
/* Parameters have been encoded. Now
* encrypt the Data.
*/
result = encrypt_data (data, &enc_params, &key, &tmp);
if (result < 0)
{
gnutls_assert ();
goto error;
}
/* write the encrypted data.
*/
result =
/* write the encrypted data.
*/
result =
asn1_write_value (pkcs7_asn,
"encryptedContentInfo.encryptedContent", tmp.data,
tmp.size);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
"encryptedContentInfo.encryptedContent", tmp.data,
tmp.size);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
_gnutls_free_datum (&tmp);
_gnutls_free_datum (&key);
_gnutls_free_datum (&tmp);
_gnutls_free_datum (&key);
/* Now write the rest of the pkcs-7 stuff.
*/
/* Now write the rest of the pkcs-7 stuff.
*/
result = _gnutls_x509_write_uint32 (pkcs7_asn, "version", 0);
if (result < 0)
{
gnutls_assert ();
goto error;
}
result = _gnutls_x509_write_uint32 (pkcs7_asn, "version", 0);
if (result < 0)
{
gnutls_assert ();
goto error;
}
result =
result =
asn1_write_value (pkcs7_asn, "encryptedContentInfo.contentType",
DATA_OID, 1);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
DATA_OID, 1);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
result = asn1_write_value (pkcs7_asn, "unprotectedAttrs", NULL, 0);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
result = asn1_write_value (pkcs7_asn, "unprotectedAttrs", NULL, 0);
if (result != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto error;
}
/* Now encode and copy the DER stuff.
*/
result = _gnutls_x509_der_encode (pkcs7_asn, "", enc, 0);
/* Now encode and copy the DER stuff.
*/
result = _gnutls_x509_der_encode (pkcs7_asn, "", enc, 0);
asn1_delete_structure (&pkcs7_asn);
asn1_delete_structure (&pkcs7_asn);
if (result < 0)
{
gnutls_assert ();
goto error;
}
if (result < 0)
{
gnutls_assert ();
goto error;
}
error:
_gnutls_free_datum (&key);
_gnutls_free_datum (&tmp);
asn1_delete_structure (&pkcs7_asn);
return result;
}
error:
_gnutls_free_datum (&key);
_gnutls_free_datum (&tmp);
asn1_delete_structure (&pkcs7_asn);
return result;
}
#endif