mirror of
https://git.gnunet.org/libmicrohttpd.git
synced 2026-10-07 04:02:18 +03:00
formating
This commit is contained in:
1 parent
b9f09651e6
commit
6d57794092
5 files changed
+2085
-2065
No files matched your search
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
@@ -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",
|
||||
¶ms_start, ¶ms_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",
|
||||
¶ms_start, ¶ms_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",
|
||||
¶ms_start, ¶ms_end);
|
||||
if (result != ASN1_SUCCESS)
|
||||
{
|
||||
gnutls_assert ();
|
||||
return _gnutls_asn2err (result);
|
||||
}
|
||||
params_len = params_end - params_start + 1;
|
||||
"keyDerivationFunc.parameters",
|
||||
¶ms_start, ¶ms_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,
|
||||
¶ms->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);
|
||||
¶ms->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",
|
||||
¶ms->iter_count);
|
||||
if (result != ASN1_SUCCESS)
|
||||
{
|
||||
gnutls_assert ();
|
||||
goto error;
|
||||
}
|
||||
_gnutls_hard_log ("iterationCount: %d\n", params->iter_count);
|
||||
¶ms->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", ¶ms->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, ¶ms->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", ¶ms->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, ¶ms->cipher)) < 0)
|
||||
{
|
||||
gnutls_assert ();
|
||||
goto error;
|
||||
}
|
||||
if ((result = oid2cipher (oid, ¶ms->cipher)) < 0)
|
||||
{
|
||||
gnutls_assert ();
|
||||
goto error;
|
||||
}
|
||||
|
||||
result =
|
||||
result =
|
||||
asn1_der_decoding_startEnd (pbes2_asn, der->data, der->size,
|
||||
"encryptionScheme.parameters",
|
||||
¶ms_start, ¶ms_end);
|
||||
if (result != ASN1_SUCCESS)
|
||||
{
|
||||
gnutls_assert ();
|
||||
return _gnutls_asn2err (result);
|
||||
}
|
||||
params_len = params_end - params_start + 1;
|
||||
"encryptionScheme.parameters",
|
||||
¶ms_start, ¶ms_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, ¶ms->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, ¶ms->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",
|
||||
¶ms_start, ¶ms_end);
|
||||
if (result != ASN1_SUCCESS)
|
||||
{
|
||||
gnutls_assert ();
|
||||
result = _gnutls_asn2err (result);
|
||||
goto error;
|
||||
}
|
||||
params_len = params_end - params_start + 1;
|
||||
"encryptedContentInfo.contentEncryptionAlgorithm.parameters",
|
||||
¶ms_start, ¶ms_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
|
||||
Reference in new issue
Block a user