more dead code

This commit is contained in:
Christian Grothoff committed 2008-10-12 22:05:17 +00:00
1 parent fd769761a5
commit f7947e0ad9
6 files changed
+43 -2989

No files matched your search

-2
View File
@@ -1159,8 +1159,6 @@ MHD__gnutls_certificate_set_x509_crl_mem (MHD_gtls_cert_credentials_t
return ret;
}
#include <pkcs12.h>
/**
* MHD__gnutls_certificate_free_crls - Used to free all the CRLs from a MHD_gtls_cert_credentials_t structure
* @sc: is an #MHD_gtls_cert_credentials_t structure.
+2 -3
View File
@@ -20,9 +20,7 @@ dn.c dn.h \
dsa.c dsa.h \
extensions.c extensions.h \
mpi.c mpi.h \
pkcs12_bag.c \
pkcs12.c pkcs12.h \
pkcs12_encr.c \
pkcs12_encr.c pkcs12.h \
pkcs7.c pkcs7.h \
x509_privkey.c privkey.h \
privkey_pkcs8.c \
@@ -30,3 +28,4 @@ rfc2818_hostname.c rfc2818.h \
sign.c sign.h \
x509_verify.c verify.h \
x509.c x509.h
-1309
View File
@@ -1,1309 +0,0 @@
/*
* Copyright (C) 2003, 2004, 2005 Free Software Foundation
*
* Author: Nikos Mavrogiannopoulos
*
* This file is part of GNUTLS.
*
* The GNUTLS library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA
*
*/
/* Functions that relate on PKCS12 packet parsing.
*/
#include <gnutls_int.h>
#include <libtasn1.h>
#ifdef ENABLE_PKI
#include <gnutls_datum.h>
#include <gnutls_global.h>
#include <gnutls_errors.h>
#include <gnutls_num.h>
#include <common.h>
#include <x509_b64.h>
#include <pkcs12.h>
#include <dn.h>
#include <mpi.h>
#include <gc.h>
/* Decodes the PKCS #12 auth_safe, and returns the allocated raw data,
* which holds them. Returns an ASN1_TYPE of authenticatedSafe.
*/
static int
_decodeMHD_pkcs12_auth_safe (ASN1_TYPE pkcs12, ASN1_TYPE * authen_safe,
MHD_gnutls_datum_t * raw)
{
char oid[128];
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
MHD_gnutls_datum_t auth_safe = { NULL, 0 };
int tmp_size, len, result;
len = sizeof (oid) - 1;
result = MHD__asn1_read_value (pkcs12, "authSafe.contentType", oid, &len);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
if (strcmp (oid, DATA_OID) != 0)
{
MHD_gnutls_assert ();
MHD__gnutls_x509_log ("Unknown PKCS12 Content OID '%s'\n", oid);
return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE;
}
/* Step 1. Read the content data
*/
tmp_size = 0;
result =
MHD__gnutls_x509_read_value (pkcs12, "authSafe.content", &auth_safe, 1);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
/* Step 2. Extract the authenticatedSafe.
*/
if ((result = MHD__asn1_create_element
(MHD__gnutls_get_pkix (), "PKIX1.pkcs-12-AuthenticatedSafe",
&c2)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
result = MHD__asn1_der_decoding (&c2, auth_safe.data, auth_safe.size, NULL);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
if (raw == NULL)
{
MHD__gnutls_free_datum (&auth_safe);
}
else
{
raw->data = auth_safe.data;
raw->size = auth_safe.size;
}
if (authen_safe)
*authen_safe = c2;
else
MHD__asn1_delete_structure (&c2);
return 0;
cleanup:
if (c2)
MHD__asn1_delete_structure (&c2);
MHD__gnutls_free_datum (&auth_safe);
return result;
}
/**
* MHD_gnutlsMHD_pkcs12_init - This function initializes a MHD_gnutlsMHD_pkcs12_t structure
* @pkcs12: The structure to be initialized
*
* This function will initialize a PKCS12 structure. PKCS12 structures
* usually contain lists of X.509 Certificates and X.509 Certificate
* revocation lists.
*
* Returns 0 on success.
*
**/
int
MHD_gnutlsMHD_pkcs12_init (MHD_gnutlsMHD_pkcs12_t * pkcs12)
{
*pkcs12 = MHD_gnutls_calloc (1, sizeof (MHD_gnutlsMHD_pkcs12_int));
if (*pkcs12)
{
int result = MHD__asn1_create_element (MHD__gnutls_get_pkix (),
"PKIX1.pkcs-12-PFX",
&(*pkcs12)->pkcs12);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
MHD_gnutls_free (*pkcs12);
return MHD_gtls_asn2err (result);
}
return 0; /* success */
}
return GNUTLS_E_MEMORY_ERROR;
}
/**
* MHD_gnutlsMHD_pkcs12_deinit - This function deinitializes memory used by a MHD_gnutlsMHD_pkcs12_t structure
* @pkcs12: The structure to be initialized
*
* This function will deinitialize a PKCS12 structure.
*
**/
void
MHD_gnutlsMHD_pkcs12_deinit (MHD_gnutlsMHD_pkcs12_t pkcs12)
{
if (!pkcs12)
return;
if (pkcs12->pkcs12)
MHD__asn1_delete_structure (&pkcs12->pkcs12);
MHD_gnutls_free (pkcs12);
}
/**
* MHD_gnutlsMHD_pkcs12_import - This function will import a DER or PEM encoded PKCS12 structure
* @pkcs12: The structure to store the parsed PKCS12.
* @data: The DER or PEM encoded PKCS12.
* @format: One of DER or PEM
* @flags: an ORed sequence of MHD_gnutls_privkey_pkcs8_flags
*
* This function will convert the given DER or PEM encoded PKCS12
* to the native MHD_gnutlsMHD_pkcs12_t format. The output will be stored in 'pkcs12'.
*
* If the PKCS12 is PEM encoded it should have a header of "PKCS12".
*
* Returns 0 on success.
*
**/
int
MHD_gnutlsMHD_pkcs12_import (MHD_gnutlsMHD_pkcs12_t pkcs12,
const MHD_gnutls_datum_t * data,
MHD_gnutls_x509_crt_fmt_t format, unsigned int flags)
{
int result = 0, need_free = 0;
MHD_gnutls_datum_t _data;
_data.data = data->data;
_data.size = data->size;
if (pkcs12 == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
/* If the PKCS12 is in PEM format then decode it
*/
if (format == GNUTLS_X509_FMT_PEM)
{
opaque *out;
result = MHD__gnutls_fbase64_decode (PEM_PKCS12, data->data, data->size,
&out);
if (result <= 0)
{
if (result == 0)
result = GNUTLS_E_INTERNAL_ERROR;
MHD_gnutls_assert ();
return result;
}
_data.data = out;
_data.size = result;
need_free = 1;
}
result = MHD__asn1_der_decoding (&pkcs12->pkcs12, _data.data, _data.size, NULL);
if (result != ASN1_SUCCESS)
{
result = MHD_gtls_asn2err (result);
MHD_gnutls_assert ();
goto cleanup;
}
if (need_free)
MHD__gnutls_free_datum (&_data);
return 0;
cleanup:
if (need_free)
MHD__gnutls_free_datum (&_data);
return result;
}
/**
* MHD_gnutlsMHD_pkcs12_export - This function will export the pkcs12 structure
* @pkcs12: Holds the pkcs12 structure
* @format: the format of output params. One of PEM or DER.
* @output_data: will contain a structure PEM or DER encoded
* @output_data_size: holds the size of output_data (and will be
* replaced by the actual size of parameters)
*
* This function will export the pkcs12 structure to DER or PEM format.
*
* If the buffer provided is not long enough to hold the output, then
* *output_data_size will be updated and GNUTLS_E_SHORT_MEMORY_BUFFER
* will be returned.
*
* If the structure is PEM encoded, it will have a header
* of "BEGIN PKCS12".
*
* Return value: In case of failure a negative value will be
* returned, and 0 on success.
*
**/
int
MHD_gnutlsMHD_pkcs12_export (MHD_gnutlsMHD_pkcs12_t pkcs12,
MHD_gnutls_x509_crt_fmt_t format, void *output_data,
size_t * output_data_size)
{
if (pkcs12 == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
return MHD__gnutls_x509_export_int (pkcs12->pkcs12, format, PEM_PKCS12,
output_data, output_data_size);
}
static int
oid2bag (const char *oid)
{
if (strcmp (oid, BAG_PKCS8_KEY) == 0)
return GNUTLS_BAG_PKCS8_KEY;
if (strcmp (oid, BAG_PKCS8_ENCRYPTED_KEY) == 0)
return GNUTLS_BAG_PKCS8_ENCRYPTED_KEY;
if (strcmp (oid, BAG_CERTIFICATE) == 0)
return GNUTLS_BAG_CERTIFICATE;
if (strcmp (oid, BAG_CRL) == 0)
return GNUTLS_BAG_CRL;
return GNUTLS_BAG_UNKNOWN;
}
static const char *
bag_to_oid (int bag)
{
switch (bag)
{
case GNUTLS_BAG_PKCS8_KEY:
return BAG_PKCS8_KEY;
case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
return BAG_PKCS8_ENCRYPTED_KEY;
case GNUTLS_BAG_CERTIFICATE:
return BAG_CERTIFICATE;
case GNUTLS_BAG_CRL:
return BAG_CRL;
}
return NULL;
}
static inline char *
ucs2_to_ascii (char *data, int size)
{
int i, j;
for (i = 0; i < size / 2; i++)
{
j = 2 * i + 1;
if (isascii (data[j]))
data[i] = data[i * 2 + 1];
else
data[i] = '?';
}
data[i] = 0;
return data;
}
/* Decodes the SafeContents, and puts the output in
* the given bag.
*/
int
MHD_pkcs12_decode_safe_contents (const MHD_gnutls_datum_t * content,
MHD_gnutlsMHD_pkcs12_bag_t bag)
{
char oid[128], root[MAX_NAME_SIZE];
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
int len, result;
int bag_type;
MHD_gnutls_datum_t attr_val;
int count = 0, i, attributes, j;
size_t size;
/* Step 1. Extract the SEQUENCE.
*/
if ((result = MHD__asn1_create_element
(MHD__gnutls_get_pkix (), "PKIX1.pkcs-12-SafeContents",
&c2)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
result = MHD__asn1_der_decoding (&c2, content->data, content->size, NULL);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
/* Count the number of bags
*/
result = MHD__asn1_number_of_elements (c2, "", &count);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
bag->bag_elements = MIN (MAX_BAG_ELEMENTS, count);
for (i = 0; i < bag->bag_elements; i++)
{
snprintf (root, sizeof (root), "?%u.bagId", i + 1);
len = sizeof (oid);
result = MHD__asn1_read_value (c2, root, oid, &len);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
/* Read the Bag type
*/
bag_type = oid2bag (oid);
if (bag_type < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
/* Read the Bag Value
*/
snprintf (root, sizeof (root), "?%u.bagValue", i + 1);
result = MHD__gnutls_x509_read_value (c2, root, &bag->element[i].data, 0);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
if (bag_type == GNUTLS_BAG_CERTIFICATE || bag_type == GNUTLS_BAG_CRL)
{
MHD_gnutls_datum_t tmp = bag->element[i].data;
result =
MHD_pkcs12_decode_crt_bag (bag_type, &tmp, &bag->element[i].data);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
MHD__gnutls_free_datum (&tmp);
}
/* read the bag attributes
*/
snprintf (root, sizeof (root), "?%u.bagAttributes", i + 1);
result = MHD__asn1_number_of_elements (c2, root, &attributes);
if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
if (attributes < 0)
attributes = 1;
if (result != ASN1_ELEMENT_NOT_FOUND)
for (j = 0; j < attributes; j++)
{
snprintf (root, sizeof (root), "?%u.bagAttributes.?%u", i + 1,
j + 1);
result =
MHD__gnutls_x509_decode_and_read_attribute (c2, root, oid,
sizeof (oid), &attr_val,
1, 0);
if (result < 0)
{
MHD_gnutls_assert ();
continue; /* continue in case we find some known attributes */
}
if (strcmp (oid, KEY_ID_OID) == 0)
{
size = attr_val.size;
result =
MHD__gnutls_x509_decode_octet_string (NULL, attr_val.data, size,
attr_val.data, &size);
attr_val.size = size;
if (result < 0)
{
MHD__gnutls_free_datum (&attr_val);
MHD_gnutls_assert ();
MHD__gnutls_x509_log
("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid);
continue;
}
bag->element[i].local_key_id = attr_val;
}
else if (strcmp (oid, FRIENDLY_NAME_OID) == 0)
{
size = attr_val.size;
result =
MHD__gnutls_x509_decode_octet_string ("BMPString",
attr_val.data, size,
attr_val.data, &size);
attr_val.size = size;
if (result < 0)
{
MHD__gnutls_free_datum (&attr_val);
MHD_gnutls_assert ();
MHD__gnutls_x509_log
("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid);
continue;
}
bag->element[i].friendly_name =
ucs2_to_ascii (attr_val.data, attr_val.size);
}
else
{
MHD__gnutls_free_datum (&attr_val);
MHD__gnutls_x509_log
("Unknown PKCS12 Bag Attribute OID '%s'\n", oid);
}
}
bag->element[i].type = bag_type;
}
MHD__asn1_delete_structure (&c2);
return 0;
cleanup:
if (c2)
MHD__asn1_delete_structure (&c2);
return result;
}
static int
_parse_safe_contents (ASN1_TYPE sc, const char *sc_name,
MHD_gnutlsMHD_pkcs12_bag_t bag)
{
MHD_gnutls_datum_t content = { NULL, 0 };
int result;
/* Step 1. Extract the content.
*/
result = MHD__gnutls_x509_read_value (sc, sc_name, &content, 1);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
result = MHD_pkcs12_decode_safe_contents (&content, bag);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
MHD__gnutls_free_datum (&content);
return 0;
cleanup:
MHD__gnutls_free_datum (&content);
return result;
}
/**
* MHD_gnutlsMHD_pkcs12_get_bag - This function returns a Bag from a PKCS12 structure
* @pkcs12: should contain a MHD_gnutlsMHD_pkcs12_t structure
* @indx: contains the index of the bag to extract
* @bag: An initialized bag, where the contents of the bag will be copied
*
* This function will return a Bag from the PKCS12 structure.
* Returns 0 on success.
*
* After the last Bag has been read GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
* will be returned.
*
**/
int
MHD_gnutlsMHD_pkcs12_get_bag (MHD_gnutlsMHD_pkcs12_t pkcs12,
int indx, MHD_gnutlsMHD_pkcs12_bag_t bag)
{
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
int result, len;
char root2[MAX_NAME_SIZE];
char oid[128];
if (pkcs12 == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
/* Step 1. decode the data.
*/
result = _decodeMHD_pkcs12_auth_safe (pkcs12->pkcs12, &c2, NULL);
if (result < 0)
{
MHD_gnutls_assert ();
return result;
}
/* Step 2. Parse the AuthenticatedSafe
*/
snprintf (root2, sizeof (root2), "?%u.contentType", indx + 1);
len = sizeof (oid) - 1;
result = MHD__asn1_read_value (c2, root2, oid, &len);
if (result == ASN1_ELEMENT_NOT_FOUND)
{
result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
goto cleanup;
}
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
/* Not encrypted Bag
*/
snprintf (root2, sizeof (root2), "?%u.content", indx + 1);
if (strcmp (oid, DATA_OID) == 0)
{
result = _parse_safe_contents (c2, root2, bag);
goto cleanup;
}
/* ENC_DATA_OID needs decryption */
bag->element[0].type = GNUTLS_BAG_ENCRYPTED;
bag->bag_elements = 1;
result = MHD__gnutls_x509_read_value (c2, root2, &bag->element[0].data, 0);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
result = 0;
cleanup:
if (c2)
MHD__asn1_delete_structure (&c2);
return result;
}
/* Creates an empty PFX structure for the PKCS12 structure.
*/
static int
create_empty_pfx (ASN1_TYPE pkcs12)
{
uint8_t three = 3;
int result;
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
/* Use version 3
*/
result = MHD__asn1_write_value (pkcs12, "version", &three, 1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
/* Write the content type of the data
*/
result = MHD__asn1_write_value (pkcs12, "authSafe.contentType", DATA_OID, 1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
/* Check if the authenticatedSafe content is empty, and encode a
* null one in that case.
*/
if ((result = MHD__asn1_create_element
(MHD__gnutls_get_pkix (), "PKIX1.pkcs-12-AuthenticatedSafe",
&c2)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
result =
MHD__gnutls_x509_der_encode_and_copy (c2, "", pkcs12, "authSafe.content", 1);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
MHD__asn1_delete_structure (&c2);
return 0;
cleanup:
MHD__asn1_delete_structure (&c2);
return result;
}
/**
* MHD_gnutlsMHD_pkcs12_set_bag - This function inserts a Bag into a PKCS12 structure
* @pkcs12: should contain a MHD_gnutlsMHD_pkcs12_t structure
* @bag: An initialized bag
*
* This function will insert a Bag into the PKCS12 structure.
* Returns 0 on success.
*
**/
int
MHD_gnutlsMHD_pkcs12_set_bag (MHD_gnutlsMHD_pkcs12_t pkcs12, MHD_gnutlsMHD_pkcs12_bag_t bag)
{
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
ASN1_TYPE safe_cont = ASN1_TYPE_EMPTY;
int result;
int enc = 0, dum = 1;
char null;
if (pkcs12 == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
/* Step 1. Check if the pkcs12 structure is empty. In that
* case generate an empty PFX.
*/
result = MHD__asn1_read_value (pkcs12->pkcs12, "authSafe.content", &null, &dum);
if (result == ASN1_VALUE_NOT_FOUND)
{
result = create_empty_pfx (pkcs12->pkcs12);
if (result < 0)
{
MHD_gnutls_assert ();
return result;
}
}
/* Step 2. decode the authenticatedSafe.
*/
result = _decodeMHD_pkcs12_auth_safe (pkcs12->pkcs12, &c2, NULL);
if (result < 0)
{
MHD_gnutls_assert ();
return result;
}
/* Step 3. Encode the bag elements into a SafeContents
* structure.
*/
result = MHD_pkcs12_encode_safe_contents (bag, &safe_cont, &enc);
if (result < 0)
{
MHD_gnutls_assert ();
return result;
}
/* Step 4. Insert the encoded SafeContents into the AuthenticatedSafe
* structure.
*/
result = MHD__asn1_write_value (c2, "", "NEW", 1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
if (enc)
result = MHD__asn1_write_value (c2, "?LAST.contentType", ENC_DATA_OID, 1);
else
result = MHD__asn1_write_value (c2, "?LAST.contentType", DATA_OID, 1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
if (enc)
{
/* Encrypted packets are written directly.
*/
result =
MHD__asn1_write_value (c2, "?LAST.content",
bag->element[0].data.data,
bag->element[0].data.size);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
}
else
{
result =
MHD__gnutls_x509_der_encode_and_copy (safe_cont, "", c2,
"?LAST.content", 1);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
}
MHD__asn1_delete_structure (&safe_cont);
/* Step 5. Reencode and copy the AuthenticatedSafe into the pkcs12
* structure.
*/
result =
MHD__gnutls_x509_der_encode_and_copy (c2, "", pkcs12->pkcs12,
"authSafe.content", 1);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
MHD__asn1_delete_structure (&c2);
return 0;
cleanup:
MHD__asn1_delete_structure (&c2);
MHD__asn1_delete_structure (&safe_cont);
return result;
}
/**
* MHD_gnutlsMHD_pkcs12_generate_mac - This function generates the MAC of the PKCS12 structure
* @pkcs12: should contain a MHD_gnutlsMHD_pkcs12_t structure
* @pass: The password for the MAC
*
* This function will generate a MAC for the PKCS12 structure.
* Returns 0 on success.
*
**/
int
MHD_gnutlsMHD_pkcs12_generate_mac (MHD_gnutlsMHD_pkcs12_t pkcs12, const char *pass)
{
opaque salt[8], key[20];
int result;
mac_hd_t td1 = NULL;
MHD_gnutls_datum_t tmp = { NULL, 0 };
opaque sha_mac[20];
if (pkcs12 == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
/* Generate the salt.
*/
if (MHD_gc_nonce (salt, sizeof (salt)) != GC_OK)
{
MHD_gnutls_assert ();
return GNUTLS_E_RANDOM_FAILED;
}
/* Write the salt into the structure.
*/
result =
MHD__asn1_write_value (pkcs12->pkcs12, "macData.macSalt", salt, sizeof (salt));
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
/* Generate the key.
*/
result = MHD_pkcs12_string_to_key (3 /*MAC*/, salt, sizeof (salt),
1, pass, sizeof (key), key);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
/* Get the data to be MACed
*/
result = _decodeMHD_pkcs12_auth_safe (pkcs12->pkcs12, NULL, &tmp);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
/* MAC the data
*/
td1 = MHD_gtls_MHD_hmac_init (MHD_GNUTLS_MAC_SHA1, key, sizeof (key));
if (td1 == GNUTLS_MAC_FAILED)
{
MHD_gnutls_assert ();
result = GNUTLS_E_INTERNAL_ERROR;
goto cleanup;
}
MHD_gnutls_hash (td1, tmp.data, tmp.size);
MHD__gnutls_free_datum (&tmp);
MHD_gnutls_MHD_hmac_deinit (td1, sha_mac);
result =
MHD__asn1_write_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac,
sizeof (sha_mac));
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
result =
MHD__asn1_write_value (pkcs12->pkcs12,
"macData.mac.digestAlgorithm.parameters", NULL, 0);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
result =
MHD__asn1_write_value (pkcs12->pkcs12,
"macData.mac.digestAlgorithm.algorithm", HASH_OID_SHA1,
1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
return 0;
cleanup:
MHD__gnutls_free_datum (&tmp);
return result;
}
/**
* MHD_gnutlsMHD_pkcs12_verify_mac - This function verifies the MAC of the PKCS12 structure
* @pkcs12: should contain a MHD_gnutlsMHD_pkcs12_t structure
* @pass: The password for the MAC
*
* This function will verify the MAC for the PKCS12 structure.
* Returns 0 on success.
*
**/
int
MHD_gnutlsMHD_pkcs12_verify_mac (MHD_gnutlsMHD_pkcs12_t pkcs12, const char *pass)
{
opaque key[20];
int result;
unsigned int iter;
int len;
mac_hd_t td1 = NULL;
MHD_gnutls_datum_t tmp = { NULL, 0 }, salt =
{
NULL, 0};
opaque sha_mac[20];
opaque sha_mac_orig[20];
if (pkcs12 == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
/* read the iterations
*/
result =
MHD__gnutls_x509_read_uint (pkcs12->pkcs12, "macData.iterations", &iter);
if (result < 0)
{
iter = 1; /* the default */
}
/* Read the salt from the structure.
*/
result =
MHD__gnutls_x509_read_value (pkcs12->pkcs12, "macData.macSalt", &salt, 0);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
/* Generate the key.
*/
result = MHD_pkcs12_string_to_key (3 /*MAC*/, salt.data, salt.size,
iter, pass, sizeof (key), key);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
MHD__gnutls_free_datum (&salt);
/* Get the data to be MACed
*/
result = _decodeMHD_pkcs12_auth_safe (pkcs12->pkcs12, NULL, &tmp);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
/* MAC the data
*/
td1 = MHD_gtls_MHD_hmac_init (MHD_GNUTLS_MAC_SHA1, key, sizeof (key));
if (td1 == GNUTLS_MAC_FAILED)
{
MHD_gnutls_assert ();
result = GNUTLS_E_INTERNAL_ERROR;
goto cleanup;
}
MHD_gnutls_hash (td1, tmp.data, tmp.size);
MHD__gnutls_free_datum (&tmp);
MHD_gnutls_MHD_hmac_deinit (td1, sha_mac);
len = sizeof (sha_mac_orig);
result =
MHD__asn1_read_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac_orig,
&len);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
if (memcmp (sha_mac_orig, sha_mac, sizeof (sha_mac)) != 0)
{
MHD_gnutls_assert ();
return GNUTLS_E_MAC_VERIFY_FAILED;
}
return 0;
cleanup:
MHD__gnutls_free_datum (&tmp);
MHD__gnutls_free_datum (&salt);
return result;
}
static int
write_attributes (MHD_gnutlsMHD_pkcs12_bag_t bag, int elem,
ASN1_TYPE c2, const char *where)
{
int result;
char root[128];
/* If the bag attributes are empty, then write
* nothing to the attribute field.
*/
if (bag->element[elem].friendly_name == NULL &&
bag->element[elem].local_key_id.data == NULL)
{
/* no attributes
*/
result = MHD__asn1_write_value (c2, where, NULL, 0);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
return 0;
}
if (bag->element[elem].local_key_id.data != NULL)
{
/* Add a new Attribute
*/
result = MHD__asn1_write_value (c2, where, "NEW", 1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
MHD_gtls_str_cpy (root, sizeof (root), where);
MHD_gtls_str_cat (root, sizeof (root), ".?LAST");
result =
MHD__gnutls_x509_encode_and_write_attribute (KEY_ID_OID, c2, root,
bag->element[elem].
local_key_id.data,
bag->element[elem].
local_key_id.size, 1);
if (result < 0)
{
MHD_gnutls_assert ();
return result;
}
}
if (bag->element[elem].friendly_name != NULL)
{
opaque *name;
int size, i;
const char *p;
/* Add a new Attribute
*/
result = MHD__asn1_write_value (c2, where, "NEW", 1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
/* convert name to BMPString
*/
size = strlen (bag->element[elem].friendly_name) * 2;
name = MHD_gnutls_malloc (size);
if (name == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_MEMORY_ERROR;
}
p = bag->element[elem].friendly_name;
for (i = 0; i < size; i += 2)
{
name[i] = 0;
name[i + 1] = *p;
p++;
}
MHD_gtls_str_cpy (root, sizeof (root), where);
MHD_gtls_str_cat (root, sizeof (root), ".?LAST");
result =
MHD__gnutls_x509_encode_and_write_attribute (FRIENDLY_NAME_OID, c2,
root, name, size, 1);
MHD_gnutls_free (name);
if (result < 0)
{
MHD_gnutls_assert ();
return result;
}
}
return 0;
}
/* Encodes the bag into a SafeContents structure, and puts the output in
* the given datum. Enc is set to non zero if the data are encrypted;
*/
int
MHD_pkcs12_encode_safe_contents (MHD_gnutlsMHD_pkcs12_bag_t bag, ASN1_TYPE * contents,
int *enc)
{
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
int result;
int i;
const char *oid;
if (bag->element[0].type == GNUTLS_BAG_ENCRYPTED && enc)
{
*enc = 1;
return 0; /* ENCRYPTED BAG, do nothing. */
}
else if (enc)
*enc = 0;
/* Step 1. Create the SEQUENCE.
*/
if ((result = MHD__asn1_create_element
(MHD__gnutls_get_pkix (), "PKIX1.pkcs-12-SafeContents",
&c2)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
for (i = 0; i < bag->bag_elements; i++)
{
oid = bag_to_oid (bag->element[i].type);
if (oid == NULL)
{
MHD_gnutls_assert ();
continue;
}
result = MHD__asn1_write_value (c2, "", "NEW", 1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
/* Copy the bag type.
*/
result = MHD__asn1_write_value (c2, "?LAST.bagId", oid, 1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
/* Set empty attributes
*/
result = write_attributes (bag, i, c2, "?LAST.bagAttributes");
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
/* Copy the Bag Value
*/
if (bag->element[i].type == GNUTLS_BAG_CERTIFICATE ||
bag->element[i].type == GNUTLS_BAG_CRL)
{
MHD_gnutls_datum_t tmp;
/* in that case encode it to a CertBag or
* a CrlBag.
*/
result =
MHD_pkcs12_encode_crt_bag (bag->element[i].type,
&bag->element[i].data, &tmp);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
result = MHD__gnutls_x509_write_value (c2, "?LAST.bagValue", &tmp, 0);
MHD__gnutls_free_datum (&tmp);
}
else
{
result = MHD__gnutls_x509_write_value (c2, "?LAST.bagValue",
&bag->element[i].data, 0);
}
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
}
/* Encode the data and copy them into the datum
*/
*contents = c2;
return 0;
cleanup:
if (c2)
MHD__asn1_delete_structure (&c2);
return result;
}
#endif /* ENABLE_PKI */
+34 -74
View File
@@ -37,15 +37,15 @@ extern "C"
/* PKCS12 structures handling
*/
struct MHD_gnutlsMHD_pkcs12_int;
struct MHD_gnutls_pkcs12_int;
struct MHD_gnutlsMHD_pkcs12_bag_int;
typedef struct MHD_gnutlsMHD_pkcs12_int
struct MHD_gnutls_pkcs12_bag_int;
typedef struct MHD_gnutls_pkcs12_int
{
ASN1_TYPE pkcs12;
} MHD_gnutlsMHD_pkcs12_int;
} MHD_gnutls_pkcs12_int;
typedef enum MHD_gnutlsMHD_pkcs12_bag_type_t
typedef enum MHD_gnutls_pkcs12_bag_type_t
{
GNUTLS_BAG_EMPTY = 0,
@@ -55,73 +55,62 @@ extern "C"
GNUTLS_BAG_CRL,
GNUTLS_BAG_ENCRYPTED = 10,
GNUTLS_BAG_UNKNOWN = 20
} MHD_gnutlsMHD_pkcs12_bag_type_t;
} MHD_gnutls_pkcs12_bag_type_t;
struct bag_element
{
MHD_gnutls_datum_t data;
MHD_gnutlsMHD_pkcs12_bag_type_t type;
MHD_gnutls_pkcs12_bag_type_t type;
MHD_gnutls_datum_t local_key_id;
char *friendly_name;
};
typedef struct MHD_gnutlsMHD_pkcs12_bag_int
typedef struct MHD_gnutls_pkcs12_bag_int
{
struct bag_element element[MAX_BAG_ELEMENTS];
int bag_elements;
} MHD_gnutlsMHD_pkcs12_bag_int;
} MHD_gnutls_pkcs12_bag_int;
/* Bag attributes */
#define FRIENDLY_NAME_OID "1.2.840.113549.1.9.20"
#define KEY_ID_OID "1.2.840.113549.1.9.21"
typedef struct MHD_gnutlsMHD_pkcs12_int *MHD_gnutlsMHD_pkcs12_t;
typedef struct MHD_gnutlsMHD_pkcs12_bag_int *MHD_gnutlsMHD_pkcs12_bag_t;
typedef struct MHD_gnutls_pkcs12_int *MHD_gnutls_pkcs12_t;
typedef struct MHD_gnutls_pkcs12_bag_int *MHD_gnutls_pkcs12_bag_t;
int MHD_gnutlsMHD_pkcs12_init (MHD_gnutlsMHD_pkcs12_t * pkcs12);
void MHD_gnutlsMHD_pkcs12_deinit (MHD_gnutlsMHD_pkcs12_t pkcs12);
int MHD_gnutlsMHD_pkcs12_import (MHD_gnutlsMHD_pkcs12_t pkcs12,
int MHD_gnutls_pkcs12_init (MHD_gnutls_pkcs12_t * pkcs12);
void MHD_gnutls_pkcs12_deinit (MHD_gnutls_pkcs12_t pkcs12);
int MHD_gnutls_pkcs12_import (MHD_gnutls_pkcs12_t pkcs12,
const MHD_gnutls_datum_t * data,
MHD_gnutls_x509_crt_fmt_t format, unsigned int flags);
int MHD_gnutlsMHD_pkcs12_export (MHD_gnutlsMHD_pkcs12_t pkcs12,
int MHD_gnutls_pkcs12_export (MHD_gnutls_pkcs12_t pkcs12,
MHD_gnutls_x509_crt_fmt_t format,
void *output_data, size_t * output_data_size);
int MHD_gnutlsMHD_pkcs12_get_bag (MHD_gnutlsMHD_pkcs12_t pkcs12,
int indx, MHD_gnutlsMHD_pkcs12_bag_t bag);
int MHD_gnutlsMHD_pkcs12_set_bag (MHD_gnutlsMHD_pkcs12_t pkcs12, MHD_gnutlsMHD_pkcs12_bag_t bag);
int MHD_gnutlsMHD_pkcs12_generate_mac (MHD_gnutlsMHD_pkcs12_t pkcs12, const char *pass);
int MHD_gnutlsMHD_pkcs12_verify_mac (MHD_gnutlsMHD_pkcs12_t pkcs12, const char *pass);
int MHD_gnutlsMHD_pkcs12_bag_decrypt (MHD_gnutlsMHD_pkcs12_bag_t bag, const char *pass);
int MHD_gnutlsMHD_pkcs12_bag_encrypt (MHD_gnutlsMHD_pkcs12_bag_t bag,
int MHD_gnutls_pkcs12_bag_decrypt (MHD_gnutls_pkcs12_bag_t bag, const char *pass);
int MHD_gnutls_pkcs12_bag_encrypt (MHD_gnutls_pkcs12_bag_t bag,
const char *pass, unsigned int flags);
MHD_gnutlsMHD_pkcs12_bag_type_t MHD_gnutlsMHD_pkcs12_bag_get_type (MHD_gnutlsMHD_pkcs12_bag_t
bag, int indx);
int MHD_gnutlsMHD_pkcs12_bag_get_data (MHD_gnutlsMHD_pkcs12_bag_t bag,
int MHD_gnutls_pkcs12_bag_get_data (MHD_gnutls_pkcs12_bag_t bag,
int indx, MHD_gnutls_datum_t * data);
int MHD_gnutlsMHD_pkcs12_bag_set_data (MHD_gnutlsMHD_pkcs12_bag_t bag,
MHD_gnutlsMHD_pkcs12_bag_type_t type,
int MHD_gnutls_pkcs12_bag_set_data (MHD_gnutls_pkcs12_bag_t bag,
MHD_gnutls_pkcs12_bag_type_t type,
const MHD_gnutls_datum_t * data);
int MHD_gnutlsMHD_pkcs12_bag_set_crl (MHD_gnutlsMHD_pkcs12_bag_t bag,
int MHD_gnutls_pkcs12_bag_set_crl (MHD_gnutls_pkcs12_bag_t bag,
MHD_gnutls_x509_crl_t crl);
int MHD_gnutlsMHD_pkcs12_bag_set_crt (MHD_gnutlsMHD_pkcs12_bag_t bag,
int MHD_gnutls_pkcs12_bag_set_crt (MHD_gnutls_pkcs12_bag_t bag,
MHD_gnutls_x509_crt_t crt);
int MHD_gnutlsMHD_pkcs12_bag_init (MHD_gnutlsMHD_pkcs12_bag_t * bag);
void MHD_gnutlsMHD_pkcs12_bag_deinit (MHD_gnutlsMHD_pkcs12_bag_t bag);
int MHD_gnutlsMHD_pkcs12_bag_get_count (MHD_gnutlsMHD_pkcs12_bag_t bag);
int MHD_gnutls_pkcs12_bag_get_count (MHD_gnutls_pkcs12_bag_t bag);
int MHD_gnutlsMHD_pkcs12_bag_get_key_id (MHD_gnutlsMHD_pkcs12_bag_t bag,
int MHD_gnutls_pkcs12_bag_get_key_id (MHD_gnutls_pkcs12_bag_t bag,
int indx, MHD_gnutls_datum_t * id);
int MHD_gnutlsMHD_pkcs12_bag_set_key_id (MHD_gnutlsMHD_pkcs12_bag_t bag,
int MHD_gnutls_pkcs12_bag_set_key_id (MHD_gnutls_pkcs12_bag_t bag,
int indx, const MHD_gnutls_datum_t * id);
int MHD_gnutlsMHD_pkcs12_bag_get_friendly_name (MHD_gnutlsMHD_pkcs12_bag_t bag,
int MHD_gnutls_pkcs12_bag_get_friendly_name (MHD_gnutls_pkcs12_bag_t bag,
int indx, char **name);
int MHD_gnutlsMHD_pkcs12_bag_set_friendly_name (MHD_gnutlsMHD_pkcs12_bag_t bag,
int MHD_gnutls_pkcs12_bag_set_friendly_name (MHD_gnutls_pkcs12_bag_t bag,
int indx, const char *name);
#ifdef __cplusplus
@@ -138,17 +127,13 @@ extern "C"
#define DATA_OID "1.2.840.113549.1.7.1"
#define ENC_DATA_OID "1.2.840.113549.1.7.6"
int MHD_gnutlsMHD_pkcs12_init (MHD_gnutlsMHD_pkcs12_t * pkcs12);
void MHD_gnutlsMHD_pkcs12_deinit (MHD_gnutlsMHD_pkcs12_t pkcs12);
int MHD_gnutlsMHD_pkcs12_import (MHD_gnutlsMHD_pkcs12_t pkcs12,
const MHD_gnutls_datum_t * data,
MHD_gnutls_x509_crt_fmt_t format, unsigned int flags);
int MHD_gnutlsMHD_pkcs12_get_bag (MHD_gnutlsMHD_pkcs12_t pkcs12,
int indx, MHD_gnutlsMHD_pkcs12_bag_t bag);
int MHD_gnutlsMHD_pkcs12_bag_init (MHD_gnutlsMHD_pkcs12_bag_t * bag);
void MHD_gnutlsMHD_pkcs12_bag_deinit (MHD_gnutlsMHD_pkcs12_bag_t bag);
typedef enum schema_id
{
PBES2, /* the stuff in PKCS #5 */
PKCS12_3DES_SHA1, /* the stuff in PKCS #12 */
PKCS12_ARCFOUR_SHA1,
PKCS12_RC2_40_SHA1
} schema_id;
int MHD_pkcs12_string_to_key (unsigned int id,
const opaque * salt,
@@ -157,29 +142,4 @@ int MHD_pkcs12_string_to_key (unsigned int id,
const char *pw,
unsigned int req_keylen, opaque * keybuf);
int MHD__gnutls_pkcs7_decrypt_data (const MHD_gnutls_datum_t * data,
const char *password, MHD_gnutls_datum_t * dec);
typedef enum schema_id
{
PBES2, /* the stuff in PKCS #5 */
PKCS12_3DES_SHA1, /* the fucking stuff in PKCS #12 */
PKCS12_ARCFOUR_SHA1,
PKCS12_RC2_40_SHA1
} schema_id;
int MHD__gnutls_pkcs7_encrypt_data (schema_id schema,
const MHD_gnutls_datum_t * data,
const char *password, MHD_gnutls_datum_t * enc);
int MHD_pkcs12_decode_safe_contents (const MHD_gnutls_datum_t * content,
MHD_gnutlsMHD_pkcs12_bag_t bag);
int MHD_pkcs12_encode_safe_contents (MHD_gnutlsMHD_pkcs12_bag_t bag,
ASN1_TYPE * content, int *enc);
int MHD_pkcs12_decode_crt_bag (MHD_gnutlsMHD_pkcs12_bag_type_t type,
const MHD_gnutls_datum_t * in, MHD_gnutls_datum_t * out);
int MHD_pkcs12_encode_crt_bag (MHD_gnutlsMHD_pkcs12_bag_type_t type,
const MHD_gnutls_datum_t * raw, MHD_gnutls_datum_t * out);
#endif /* GNUTLS_PKCS12_H */
-770
View File
@@ -1,770 +0,0 @@
/*
* Copyright (C) 2003, 2004, 2005 Free Software Foundation
*
* Author: Nikos Mavrogiannopoulos
*
* This file is part of GNUTLS.
*
* The GNUTLS library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA
*
*/
/* Functions that relate on PKCS12 Bag packet parsing.
*/
#include <gnutls_int.h>
#ifdef ENABLE_PKI
#include <gnutls_datum.h>
#include <gnutls_global.h>
#include <gnutls_errors.h>
#include <common.h>
#include <pkcs12.h>
#include <privkey.h>
/**
* MHD_gnutlsMHD_pkcs12_bag_init - This function initializes a MHD_gnutlsMHD_pkcs12_bag_t structure
* @bag: The structure to be initialized
*
* This function will initialize a PKCS12 bag structure. PKCS12 Bags
* usually contain private keys, lists of X.509 Certificates and X.509 Certificate
* revocation lists.
*
* Returns 0 on success.
*
**/
int
MHD_gnutlsMHD_pkcs12_bag_init (MHD_gnutlsMHD_pkcs12_bag_t * bag)
{
*bag = MHD_gnutls_calloc (1, sizeof (MHD_gnutlsMHD_pkcs12_bag_int));
if (*bag)
{
return 0; /* success */
}
return GNUTLS_E_MEMORY_ERROR;
}
static inline void
MHD_pkcs12_bag_free_data (MHD_gnutlsMHD_pkcs12_bag_t bag)
{
int i;
for (i = 0; i < bag->bag_elements; i++)
{
MHD__gnutls_free_datum (&bag->element[i].data);
MHD__gnutls_free_datum (&bag->element[i].local_key_id);
MHD_gnutls_free (bag->element[i].friendly_name);
bag->element[i].friendly_name = NULL;
bag->element[i].type = 0;
}
}
/**
* MHD_gnutlsMHD_pkcs12_bag_deinit - This function deinitializes memory used by a MHD_gnutlsMHD_pkcs12_t structure
* @bag: The structure to be initialized
*
* This function will deinitialize a PKCS12 Bag structure.
*
**/
void
MHD_gnutlsMHD_pkcs12_bag_deinit (MHD_gnutlsMHD_pkcs12_bag_t bag)
{
if (!bag)
return;
MHD_pkcs12_bag_free_data (bag);
MHD_gnutls_free (bag);
}
/**
* MHD_gnutlsMHD_pkcs12_bag_get_type - This function returns the bag's type
* @bag: The bag
* @indx: The element of the bag to get the type
*
* This function will return the bag's type. One of the MHD_gnutlsMHD_pkcs12_bag_type_t
* enumerations.
*
**/
MHD_gnutlsMHD_pkcs12_bag_type_t
MHD_gnutlsMHD_pkcs12_bag_get_type (MHD_gnutlsMHD_pkcs12_bag_t bag, int indx)
{
if (bag == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
if (indx >= bag->bag_elements)
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
return bag->element[indx].type;
}
/**
* MHD_gnutlsMHD_pkcs12_bag_get_count - This function returns the bag's elements count
* @bag: The bag
*
* This function will return the number of the elements withing the bag.
*
**/
int
MHD_gnutlsMHD_pkcs12_bag_get_count (MHD_gnutlsMHD_pkcs12_bag_t bag)
{
if (bag == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
return bag->bag_elements;
}
/**
* MHD_gnutlsMHD_pkcs12_bag_get_data - This function returns the bag's data
* @bag: The bag
* @indx: The element of the bag to get the data from
* @data: where the bag's data will be. Should be treated as constant.
*
* This function will return the bag's data. The data is a constant
* that is stored into the bag. Should not be accessed after the bag
* is deleted.
*
* Returns 0 on success and a negative error code on error.
*
**/
int
MHD_gnutlsMHD_pkcs12_bag_get_data (MHD_gnutlsMHD_pkcs12_bag_t bag, int indx,
MHD_gnutls_datum_t * data)
{
if (bag == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
if (indx >= bag->bag_elements)
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
data->data = bag->element[indx].data.data;
data->size = bag->element[indx].data.size;
return 0;
}
#define X509_CERT_OID "1.2.840.113549.1.9.22.1"
#define X509_CRL_OID "1.2.840.113549.1.9.23.1"
int
MHD_pkcs12_decode_crt_bag (MHD_gnutlsMHD_pkcs12_bag_type_t type,
const MHD_gnutls_datum_t * in, MHD_gnutls_datum_t * out)
{
int ret;
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
if (type == GNUTLS_BAG_CERTIFICATE)
{
if ((ret = MHD__asn1_create_element (MHD__gnutls_get_pkix (),
"PKIX1.pkcs-12-CertBag",
&c2)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
ret = MHD_gtls_asn2err (ret);
goto cleanup;
}
ret = MHD__asn1_der_decoding (&c2, in->data, in->size, NULL);
if (ret != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
ret = MHD_gtls_asn2err (ret);
goto cleanup;
}
ret = MHD__gnutls_x509_read_value (c2, "certValue", out, 1);
if (ret < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
}
else
{ /* CRL */
if ((ret = MHD__asn1_create_element (MHD__gnutls_get_pkix (),
"PKIX1.pkcs-12-CRLBag",
&c2)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
ret = MHD_gtls_asn2err (ret);
goto cleanup;
}
ret = MHD__asn1_der_decoding (&c2, in->data, in->size, NULL);
if (ret != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
ret = MHD_gtls_asn2err (ret);
goto cleanup;
}
ret = MHD__gnutls_x509_read_value (c2, "crlValue", out, 1);
if (ret < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
}
MHD__asn1_delete_structure (&c2);
return 0;
cleanup:
MHD__asn1_delete_structure (&c2);
return ret;
}
int
MHD_pkcs12_encode_crt_bag (MHD_gnutlsMHD_pkcs12_bag_type_t type,
const MHD_gnutls_datum_t * raw, MHD_gnutls_datum_t * out)
{
int ret;
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
if (type == GNUTLS_BAG_CERTIFICATE)
{
if ((ret = MHD__asn1_create_element (MHD__gnutls_get_pkix (),
"PKIX1.pkcs-12-CertBag",
&c2)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
ret = MHD_gtls_asn2err (ret);
goto cleanup;
}
ret = MHD__asn1_write_value (c2, "certId", X509_CERT_OID, 1);
if (ret != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
ret = MHD_gtls_asn2err (ret);
goto cleanup;
}
ret = MHD__gnutls_x509_write_value (c2, "certValue", raw, 1);
if (ret < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
}
else
{ /* CRL */
if ((ret = MHD__asn1_create_element (MHD__gnutls_get_pkix (),
"PKIX1.pkcs-12-CRLBag",
&c2)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
ret = MHD_gtls_asn2err (ret);
goto cleanup;
}
ret = MHD__asn1_write_value (c2, "crlId", X509_CRL_OID, 1);
if (ret != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
ret = MHD_gtls_asn2err (ret);
goto cleanup;
}
ret = MHD__gnutls_x509_write_value (c2, "crlValue", raw, 1);
if (ret < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
}
ret = MHD__gnutls_x509_der_encode (c2, "", out, 0);
if (ret < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
MHD__asn1_delete_structure (&c2);
return 0;
cleanup:
MHD__asn1_delete_structure (&c2);
return ret;
}
/**
* MHD_gnutlsMHD_pkcs12_bag_set_data - This function inserts data into the bag
* @bag: The bag
* @type: The data's type
* @data: the data to be copied.
*
* This function will insert the given data of the given type into the
* bag.
*
* Returns the index of the added bag on success, or a negative
* value on error.
*
**/
int
MHD_gnutlsMHD_pkcs12_bag_set_data (MHD_gnutlsMHD_pkcs12_bag_t bag,
MHD_gnutlsMHD_pkcs12_bag_type_t type,
const MHD_gnutls_datum_t * data)
{
int ret;
if (bag == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
if (bag->bag_elements == MAX_BAG_ELEMENTS - 1)
{
MHD_gnutls_assert ();
/* bag is full */
return GNUTLS_E_MEMORY_ERROR;
}
if (bag->bag_elements == 1)
{
/* A bag with a key or an encrypted bag, must have
* only one element.
*/
if (bag->element[0].type == GNUTLS_BAG_PKCS8_KEY ||
bag->element[0].type == GNUTLS_BAG_PKCS8_ENCRYPTED_KEY ||
bag->element[0].type == GNUTLS_BAG_ENCRYPTED)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
}
ret =
MHD__gnutls_set_datum (&bag->element[bag->bag_elements].data,
data->data, data->size);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
bag->element[bag->bag_elements].type = type;
bag->bag_elements++;
return bag->bag_elements - 1;
}
/**
* MHD_gnutlsMHD_pkcs12_bag_set_crt - This function inserts a certificate into the bag
* @bag: The bag
* @crt: the certificate to be copied.
*
* This function will insert the given certificate into the
* bag. This is just a wrapper over MHD_gnutlsMHD_pkcs12_bag_set_data().
*
* Returns the index of the added bag on success, or a negative
* value on failure.
*
**/
int
MHD_gnutlsMHD_pkcs12_bag_set_crt (MHD_gnutlsMHD_pkcs12_bag_t bag, MHD_gnutls_x509_crt_t crt)
{
int ret;
MHD_gnutls_datum_t data;
if (bag == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
ret = MHD__gnutls_x509_der_encode (crt->cert, "", &data, 0);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
ret = MHD_gnutlsMHD_pkcs12_bag_set_data (bag, GNUTLS_BAG_CERTIFICATE, &data);
MHD__gnutls_free_datum (&data);
return ret;
}
/**
* MHD_gnutlsMHD_pkcs12_bag_set_crl - This function inserts the CRL into the bag
* @bag: The bag
* @crl: the CRL to be copied.
*
* This function will insert the given CRL into the
* bag. This is just a wrapper over MHD_gnutlsMHD_pkcs12_bag_set_data().
*
* Returns the index of the added bag on success, or a negative
* value on failure.
*
**/
int
MHD_gnutlsMHD_pkcs12_bag_set_crl (MHD_gnutlsMHD_pkcs12_bag_t bag, MHD_gnutls_x509_crl_t crl)
{
int ret;
MHD_gnutls_datum_t data;
if (bag == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
ret = MHD__gnutls_x509_der_encode (crl->crl, "", &data, 0);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
ret = MHD_gnutlsMHD_pkcs12_bag_set_data (bag, GNUTLS_BAG_CRL, &data);
MHD__gnutls_free_datum (&data);
return ret;
}
/**
* MHD_gnutlsMHD_pkcs12_bag_set_key_id - This function sets a key ID into the bag element
* @bag: The bag
* @indx: The bag's element to add the id
* @id: the ID
*
* This function will add the given key ID, to the specified, by the index, bag
* element. The key ID will be encoded as a 'Local key identifier' bag attribute,
* which is usually used to distinguish the local private key and the certificate pair.
*
* Returns 0 on success, or a negative value on error.
*
**/
int
MHD_gnutlsMHD_pkcs12_bag_set_key_id (MHD_gnutlsMHD_pkcs12_bag_t bag, int indx,
const MHD_gnutls_datum_t * id)
{
int ret;
if (bag == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
if (indx > bag->bag_elements - 1)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
ret = MHD__gnutls_set_datum (&bag->element[indx].local_key_id,
id->data, id->size);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
return 0;
}
/**
* MHD_gnutlsMHD_pkcs12_bag_get_key_id - This function gets the key ID from the bag element
* @bag: The bag
* @indx: The bag's element to add the id
* @id: where the ID will be copied (to be treated as const)
*
* This function will return the key ID, of the specified bag element.
* The key ID is usually used to distinguish the local private key and the certificate pair.
*
* Returns 0 on success, or a negative value on error.
*
**/
int
MHD_gnutlsMHD_pkcs12_bag_get_key_id (MHD_gnutlsMHD_pkcs12_bag_t bag, int indx,
MHD_gnutls_datum_t * id)
{
if (bag == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
if (indx > bag->bag_elements - 1)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
id->data = bag->element[indx].local_key_id.data;
id->size = bag->element[indx].local_key_id.size;
return 0;
}
/**
* MHD_gnutlsMHD_pkcs12_bag_get_friendly_name - This function returns the friendly name of the bag element
* @bag: The bag
* @indx: The bag's element to add the id
* @name: will hold a pointer to the name (to be treated as const)
*
* This function will return the friendly name, of the specified bag element.
* The key ID is usually used to distinguish the local private key and the certificate pair.
*
* Returns 0 on success, or a negative value on error.
*
**/
int
MHD_gnutlsMHD_pkcs12_bag_get_friendly_name (MHD_gnutlsMHD_pkcs12_bag_t bag, int indx,
char **name)
{
if (bag == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
if (indx > bag->bag_elements - 1)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
*name = bag->element[indx].friendly_name;
return 0;
}
/**
* MHD_gnutlsMHD_pkcs12_bag_set_friendly_name - This function sets a friendly name into the bag element
* @bag: The bag
* @indx: The bag's element to add the id
* @name: the name
*
* This function will add the given key friendly name, to the specified, by the index, bag
* element. The name will be encoded as a 'Friendly name' bag attribute,
* which is usually used to set a user name to the local private key and the certificate pair.
*
* Returns 0 on success, or a negative value on error.
*
**/
int
MHD_gnutlsMHD_pkcs12_bag_set_friendly_name (MHD_gnutlsMHD_pkcs12_bag_t bag, int indx,
const char *name)
{
if (bag == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
if (indx > bag->bag_elements - 1)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
bag->element[indx].friendly_name = MHD_gnutls_strdup (name);
if (name == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_MEMORY_ERROR;
}
return 0;
}
/**
* MHD_gnutlsMHD_pkcs12_bag_decrypt - This function will decrypt an encrypted bag
* @bag: The bag
* @pass: The password used for encryption. This can only be ASCII.
*
* This function will decrypt the given encrypted bag and return 0 on success.
*
**/
int
MHD_gnutlsMHD_pkcs12_bag_decrypt (MHD_gnutlsMHD_pkcs12_bag_t bag, const char *pass)
{
int ret;
MHD_gnutls_datum_t dec;
if (bag == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
if (bag->element[0].type != GNUTLS_BAG_ENCRYPTED)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
ret = MHD__gnutls_pkcs7_decrypt_data (&bag->element[0].data, pass, &dec);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
/* decryption succeeded. Now decode the SafeContents
* stuff, and parse it.
*/
MHD__gnutls_free_datum (&bag->element[0].data);
ret = MHD_pkcs12_decode_safe_contents (&dec, bag);
MHD__gnutls_free_datum (&dec);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
return 0;
}
/**
* MHD_gnutlsMHD_pkcs12_bag_encrypt - This function will encrypt a bag
* @bag: The bag
* @pass: The password used for encryption. This can only be ASCII.
* @flags: should be one of MHD_gnutls_pkcs_encrypt_flags_t elements bitwise or'd
*
* This function will encrypt the given bag and return 0 on success.
*
**/
int
MHD_gnutlsMHD_pkcs12_bag_encrypt (MHD_gnutlsMHD_pkcs12_bag_t bag, const char *pass,
unsigned int flags)
{
int ret;
ASN1_TYPE safe_cont = ASN1_TYPE_EMPTY;
MHD_gnutls_datum_t der = { NULL, 0 };
MHD_gnutls_datum_t enc = { NULL, 0 };
schema_id id;
if (bag == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
if (bag->element[0].type == GNUTLS_BAG_ENCRYPTED)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
/* Encode the whole bag to a safe contents
* structure.
*/
ret = MHD_pkcs12_encode_safe_contents (bag, &safe_cont, NULL);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
/* DER encode the SafeContents.
*/
ret = MHD__gnutls_x509_der_encode (safe_cont, "", &der, 0);
MHD__asn1_delete_structure (&safe_cont);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
if (flags & GNUTLS_PKCS_PLAIN)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
if (flags & GNUTLS_PKCS_USE_PKCS12_ARCFOUR)
id = PKCS12_ARCFOUR_SHA1;
else if (flags & GNUTLS_PKCS_USE_PKCS12_RC2_40)
id = PKCS12_RC2_40_SHA1;
else if (flags & GNUTLS_PKCS_USE_PBES2_3DES)
id = PBES2;
else
id = PKCS12_3DES_SHA1;
/* Now encrypt them.
*/
ret = MHD__gnutls_pkcs7_encrypt_data (id, &der, pass, &enc);
MHD__gnutls_free_datum (&der);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
/* encryption succeeded.
*/
MHD_pkcs12_bag_free_data (bag);
bag->element[0].type = GNUTLS_BAG_ENCRYPTED;
bag->element[0].data = enc;
bag->bag_elements = 1;
return 0;
}
#endif /* ENABLE_PKI */
+7 -831
View File
@@ -34,8 +34,8 @@
#include <gnutls_x509.h>
#include <x509_b64.h>
#include <x509.h>
#include <dn.h>
#include <pkcs12.h>
#include <dn.h>
#include <privkey.h>
#include <extensions.h>
#include <mpi.h>
@@ -68,10 +68,6 @@ struct pbe_enc_params
int iv_size;
};
static int generate_key (schema_id schema, const char *password,
struct pbkdf2_params *kdf_params,
struct pbe_enc_params *enc_params,
MHD_gnutls_datum_t * key);
static int read_pbkdf2_params (ASN1_TYPE pbes2_asn,
const MHD_gnutls_datum_t * der,
struct pbkdf2_params *params);
@@ -85,18 +81,8 @@ static int decrypt_data (schema_id, ASN1_TYPE pkcs8_asn, const char *root,
MHD_gnutls_datum_t * decrypted_data);
static int decode_private_key_info (const MHD_gnutls_datum_t * der,
MHD_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);
static int encrypt_data (const MHD_gnutls_datum_t * plain,
const struct pbe_enc_params *enc_params,
MHD_gnutls_datum_t * key, MHD_gnutls_datum_t * encrypted);
static int readMHD_pkcs12_kdf_params (ASN1_TYPE pbes2_asn,
struct pbkdf2_params *params);
static int writeMHD_pkcs12_kdf_params (ASN1_TYPE pbes2_asn,
const struct pbkdf2_params *params);
#define PEM_PKCS8 "ENCRYPTED PRIVATE KEY"
#define PEM_UNENCRYPTED_PKCS8 "PRIVATE KEY"
@@ -104,7 +90,7 @@ static int writeMHD_pkcs12_kdf_params (ASN1_TYPE pbes2_asn,
/* Returns a negative error code if the encryption schema in
* the OID is not supported. The schema ID is returned.
*/
inline static int
static int
check_schema (const char *oid)
{
@@ -420,78 +406,6 @@ error:
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, MHD_gnutls_x509_privkey pkey)
{
int ret;
MHD_gnutls_datum tmp;
ret = MHD__gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp, 0);
if (ret < 0)
{
MHD_gnutls_assert ();
goto error;
}
ret = MHD__gnutls_x509_read_der_int (tmp.data, tmp.size, &pkey->params[4]);
MHD__gnutls_free_datum (&tmp);
if (ret < 0)
{
MHD_gnutls_assert ();
goto error;
}
ret =
MHD__gnutls_x509_read_value (pkcs8_asn, "privateKeyAlgorithm.parameters",
&tmp, 0);
if (ret < 0)
{
MHD_gnutls_assert ();
goto error;
}
ret = MHD__gnutls_x509_read_dsa_params (tmp.data, tmp.size, pkey->params);
MHD__gnutls_free_datum (&tmp);
if (ret < 0)
{
MHD_gnutls_assert ();
goto error;
}
the public key can be generated as g^x mod p
pkey->params[3] = MHD__gnutls_mpi_alloc_like (pkey->params[0]);
if (pkey->params[3] == NULL)
{
MHD_gnutls_assert ();
goto error;
}
MHD__gnutls_mpi_powm (pkey->params[3], pkey->params[2], pkey->params[4],
pkey->params[0]);
if (!pkey->crippled)
{
ret = MHD__gnutls_asn1_encode_dsa (&pkey->key, pkey->params);
if (ret < 0)
{
MHD_gnutls_assert ();
goto error;
}
}
pkey->params_size = DSA_PRIVATE_PARAMS;
return 0;
error:
MHD_gnutls_x509_privkey_deinit (pkey);
return ret;
}
*/
static int
decode_private_key_info (const MHD_gnutls_datum_t * der,
MHD_gnutls_x509_privkey_t pkey)
@@ -532,7 +446,7 @@ decode_private_key_info (const MHD_gnutls_datum_t * der,
/* we only support RSA and DSA private keys.
*/
if (strcmp (oid, PK_PKIX1_RSA_OID) == 0)
if (strcmp ((const char*) oid, PK_PKIX1_RSA_OID) == 0)
pkey->pk_algorithm = MHD_GNUTLS_PK_RSA;
else
{
@@ -824,49 +738,9 @@ error:
}
/* Writes the PBE parameters for PKCS-12 schemas.
*/
static int
writeMHD_pkcs12_kdf_params (ASN1_TYPE pbes2_asn,
const struct pbkdf2_params *kdf_params)
{
int result;
/* write the salt
*/
result =
MHD__asn1_write_value (pbes2_asn, "salt",
kdf_params->salt, kdf_params->salt_size);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
MHD__gnutls_hard_log ("salt.size: %d\n", kdf_params->salt_size);
/* write the iteration count
*/
result =
MHD__gnutls_x509_write_uint32 (pbes2_asn, "iterations",
kdf_params->iter_count);
if (result < 0)
{
MHD_gnutls_assert ();
goto error;
}
MHD__gnutls_hard_log ("iterationCount: %d\n", kdf_params->iter_count);
return 0;
error:
return result;
}
/* Converts an OID to a gnutls cipher type.
*/
inline static int
static int
oid2cipher (const char *oid, enum MHD_GNUTLS_CipherAlgorithm *algo)
{
@@ -1025,8 +899,9 @@ decrypt_data (schema_id schema, ASN1_TYPE pkcs8_asn,
if (schema == PBES2)
{
result = MHD_gc_pbkdf2_sha1 (password, strlen (password),
kdf_params->salt, kdf_params->salt_size,
kdf_params->iter_count, key, key_size);
(const char*) kdf_params->salt, kdf_params->salt_size,
kdf_params->iter_count,
(char*) key, key_size);
if (result != GC_OK)
{
@@ -1095,704 +970,5 @@ error:
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];
/* Write the key derivation algorithm
*/
result =
MHD__asn1_write_value (pbes2_asn, "keyDerivationFunc.algorithm",
PBKDF2_OID, 1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
/* Now write the key derivation and the encryption
* functions.
*/
if ((result =
MHD__asn1_create_element (MHD__gnutls_get_pkix (),
"PKIX1.pkcs-5-PBKDF2-params",
&pbkdf2_asn)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
result = MHD__asn1_write_value (pbkdf2_asn, "salt", "specified", 1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
/* write the salt
*/
result =
MHD__asn1_write_value (pbkdf2_asn, "salt.specified",
kdf_params->salt, kdf_params->salt_size);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
MHD__gnutls_hard_log ("salt.specified.size: %d\n", kdf_params->salt_size);
/* write the iteration count
*/
MHD_gtls_write_uint32 (kdf_params->iter_count, tmp);
result = MHD__asn1_write_value (pbkdf2_asn, "iterationCount", tmp, 4);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
MHD__gnutls_hard_log ("iterationCount: %d\n", kdf_params->iter_count);
/* write the keylength, if it is set.
*/
result = MHD__asn1_write_value (pbkdf2_asn, "keyLength", NULL, 0);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
/* We write an emptry prf.
*/
result = MHD__asn1_write_value (pbkdf2_asn, "prf", NULL, 0);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
/* now encode them an put the DER output
* in the keyDerivationFunc.parameters
*/
result = MHD__gnutls_x509_der_encode_and_copy (pbkdf2_asn, "",
pbes2_asn,
"keyDerivationFunc.parameters",
0);
if (result < 0)
{
MHD_gnutls_assert ();
goto error;
}
return 0;
error:
MHD__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;
/* Write the encryption algorithm
*/
result =
MHD__asn1_write_value (pbes2_asn, "encryptionScheme.algorithm",
DES_EDE3_CBC_OID, 1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
goto error;
}
MHD__gnutls_hard_log ("encryptionScheme.algorithm: %s\n", DES_EDE3_CBC_OID);
/* Now check the encryption parameters.
*/
if ((result =
MHD__asn1_create_element (MHD__gnutls_get_pkix (),
"PKIX1.pkcs-5-des-EDE3-CBC-params",
&pbe_asn)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
/* read the salt */
result = MHD__asn1_write_value (pbe_asn, "", params->iv, params->iv_size);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
MHD__gnutls_hard_log ("IV.size: %d\n", params->iv_size);
/* now encode them an put the DER output
* in the encryptionScheme.parameters
*/
result = MHD__gnutls_x509_der_encode_and_copy (pbe_asn, "",
pbes2_asn,
"encryptionScheme.parameters",
0);
if (result < 0)
{
MHD_gnutls_assert ();
goto error;
}
return 0;
error:
MHD__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, MHD_gnutls_datum_t * key)
{
opaque rnd[2];
int ret;
/* We should use the flags here to use different
* encryption algorithms etc.
*/
if (schema == PKCS12_ARCFOUR_SHA1)
enc_params->cipher = MHD_GNUTLS_CIPHER_ARCFOUR_128;
else if (schema == PKCS12_3DES_SHA1)
enc_params->cipher = MHD_GNUTLS_CIPHER_3DES_CBC;
else if (schema == PKCS12_RC2_40_SHA1)
enc_params->cipher = MHD_GNUTLS_CIPHER_RC2_40_CBC;
if (MHD_gc_pseudo_random (rnd, 2) != GC_OK)
{
MHD_gnutls_assert ();
return GNUTLS_E_RANDOM_FAILED;
}
/* generate salt */
if (schema == PBES2)
{
kdf_params->salt_size =
MIN (sizeof (kdf_params->salt), (unsigned) (10 + (rnd[1] % 10)));
}
else
kdf_params->salt_size = 8;
if (MHD_gc_pseudo_random (kdf_params->salt, kdf_params->salt_size) != GC_OK)
{
MHD_gnutls_assert ();
return GNUTLS_E_RANDOM_FAILED;
}
kdf_params->iter_count = 256 + rnd[0];
key->size = kdf_params->key_size =
MHD__gnutls_cipher_get_key_size (enc_params->cipher);
enc_params->iv_size = MHD_gtls_cipher_get_iv_size (enc_params->cipher);
key->data = MHD_gnutls_secure_malloc (key->size);
if (key->data == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_MEMORY_ERROR;
}
/* now generate the key.
*/
if (schema == PBES2)
{
ret = MHD_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)
{
MHD_gnutls_assert ();
return GNUTLS_E_ENCRYPTION_FAILED;
}
if (enc_params->iv_size &&
MHD_gc_nonce (enc_params->iv, enc_params->iv_size) != GC_OK)
{
MHD_gnutls_assert ();
return GNUTLS_E_RANDOM_FAILED;
}
}
else
{ /* PKCS12 schemas */
ret =
MHD_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)
{
MHD_gnutls_assert ();
return ret;
}
/* Now generate the IV
*/
if (enc_params->iv_size)
{
ret =
MHD_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)
{
MHD_gnutls_assert ();
return ret;
}
}
}
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;
if (schema == PBES2)
{
if ((result =
MHD__asn1_create_element (MHD__gnutls_get_pkix (),
"PKIX1.pkcs-5-PBES2-params",
&pbes2_asn)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
result = write_pbkdf2_params (pbes2_asn, kdf_params);
if (result < 0)
{
MHD_gnutls_assert ();
goto error;
}
result = write_pbe_enc_params (pbes2_asn, enc_params);
if (result < 0)
{
MHD_gnutls_assert ();
goto error;
}
result = MHD__gnutls_x509_der_encode_and_copy (pbes2_asn, "",
pkcs8_asn, where, 0);
if (result < 0)
{
MHD_gnutls_assert ();
goto error;
}
MHD__asn1_delete_structure (&pbes2_asn);
}
else
{ /* PKCS12 schemas */
if ((result =
MHD__asn1_create_element (MHD__gnutls_get_pkix (),
"PKIX1.pkcs-12-PbeParams",
&pbes2_asn)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
result = writeMHD_pkcs12_kdf_params (pbes2_asn, kdf_params);
if (result < 0)
{
MHD_gnutls_assert ();
goto error;
}
result = MHD__gnutls_x509_der_encode_and_copy (pbes2_asn, "",
pkcs8_asn, where, 0);
if (result < 0)
{
MHD_gnutls_assert ();
goto error;
}
MHD__asn1_delete_structure (&pbes2_asn);
}
return 0;
error:
MHD__asn1_delete_structure (&pbes2_asn);
return result;
}
static int
encrypt_data (const MHD_gnutls_datum_t * plain,
const struct pbe_enc_params *enc_params,
MHD_gnutls_datum_t * key, MHD_gnutls_datum_t * encrypted)
{
int result;
int data_size;
opaque *data = NULL;
MHD_gnutls_datum_t d_iv;
cipher_hd_t ch = NULL;
opaque pad, pad_size;
pad_size = MHD_gtls_cipher_get_block_size (enc_params->cipher);
if (pad_size == 1) /* stream */
pad_size = 0;
data = MHD_gnutls_malloc (plain->size + pad_size);
if (data == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_MEMORY_ERROR;
}
memcpy (data, plain->data, plain->size);
if (pad_size > 0)
{
pad = pad_size - (plain->size % pad_size);
if (pad == 0)
pad = pad_size;
memset (&data[plain->size], pad, pad);
}
else
pad = 0;
data_size = plain->size + pad;
d_iv.data = (opaque *) enc_params->iv;
d_iv.size = enc_params->iv_size;
ch = MHD_gtls_cipher_init (enc_params->cipher, key, &d_iv);
if (ch == GNUTLS_CIPHER_FAILED)
{
MHD_gnutls_assert ();
result = GNUTLS_E_ENCRYPTION_FAILED;
goto error;
}
result = MHD_gtls_cipher_encrypt (ch, data, data_size);
if (result < 0)
{
MHD_gnutls_assert ();
goto error;
}
encrypted->data = data;
encrypted->size = data_size;
MHD_gnutls_cipher_deinit (ch);
return 0;
error:
MHD_gnutls_free (data);
if (ch != NULL)
MHD_gnutls_cipher_deinit (ch);
return result;
}
/* Decrypts a PKCS #7 encryptedData. The output is allocated
* and stored in dec.
*/
int
MHD__gnutls_pkcs7_decrypt_data (const MHD_gnutls_datum_t * data,
const char *password, MHD_gnutls_datum_t * dec)
{
int result, len;
char enc_oid[64];
MHD_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 =
MHD__asn1_create_element (MHD__gnutls_get_pkix (),
"PKIX1.pkcs-7-EncryptedData",
&pkcs7_asn)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
result = MHD__asn1_der_decoding (&pkcs7_asn, data->data, data->size, NULL);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
/* Check the encryption schema OID
*/
len = sizeof (enc_oid);
result =
MHD__asn1_read_value (pkcs7_asn,
"encryptedContentInfo.contentEncryptionAlgorithm.algorithm",
enc_oid, &len);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
if ((result = check_schema (enc_oid)) < 0)
{
MHD_gnutls_assert ();
goto error;
}
schema = result;
/* Get the DER encoding of the parameters.
*/
result =
MHD__asn1_der_decoding_startEnd (pkcs7_asn, data->data, data->size,
"encryptedContentInfo.contentEncryptionAlgorithm.parameters",
&params_start, &params_end);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
params_len = params_end - params_start + 1;
result =
read_pkcs_schema_params (schema, password,
&data->data[params_start],
params_len, &kdf_params, &enc_params);
if (result < ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
/* Parameters have been decoded. Now
* decrypt the EncryptedData.
*/
result =
decrypt_data (schema, pkcs7_asn,
"encryptedContentInfo.encryptedContent", password,
&kdf_params, &enc_params, &tmp);
if (result < 0)
{
MHD_gnutls_assert ();
goto error;
}
MHD__asn1_delete_structure (&pkcs7_asn);
*dec = tmp;
return 0;
error:
MHD__asn1_delete_structure (&pbes2_asn);
MHD__asn1_delete_structure (&pkcs7_asn);
return result;
}
/* Encrypts to a PKCS #7 encryptedData. The output is allocated
* and stored in enc.
*/
int
MHD__gnutls_pkcs7_encrypt_data (schema_id schema,
const MHD_gnutls_datum_t * data,
const char *password, MHD_gnutls_datum_t * enc)
{
int result;
MHD_gnutls_datum_t key = { NULL, 0 };
MHD_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 =
MHD__asn1_create_element (MHD__gnutls_get_pkix (),
"PKIX1.pkcs-7-EncryptedData",
&pkcs7_asn)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
/* Write the encryption schema OID
*/
switch (schema)
{
case PBES2:
result =
MHD__asn1_write_value (pkcs7_asn,
"encryptedContentInfo.contentEncryptionAlgorithm.algorithm",
PBES2_OID, 1);
break;
case PKCS12_3DES_SHA1:
result =
MHD__asn1_write_value (pkcs7_asn,
"encryptedContentInfo.contentEncryptionAlgorithm.algorithm",
PKCS12_PBE_3DES_SHA1_OID, 1);
break;
case PKCS12_ARCFOUR_SHA1:
result =
MHD__asn1_write_value (pkcs7_asn,
"encryptedContentInfo.contentEncryptionAlgorithm.algorithm",
PKCS12_PBE_ARCFOUR_SHA1_OID, 1);
break;
case PKCS12_RC2_40_SHA1:
result =
MHD__asn1_write_value (pkcs7_asn,
"encryptedContentInfo.contentEncryptionAlgorithm.algorithm",
PKCS12_PBE_RC2_40_SHA1_OID, 1);
break;
}
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
/* Generate a symmetric key.
*/
result = generate_key (schema, password, &kdf_params, &enc_params, &key);
if (result < 0)
{
MHD_gnutls_assert ();
goto error;
}
result = write_schema_params (schema, pkcs7_asn,
"encryptedContentInfo.contentEncryptionAlgorithm.parameters",
&kdf_params, &enc_params);
if (result < 0)
{
MHD_gnutls_assert ();
goto error;
}
/* Parameters have been encoded. Now
* encrypt the Data.
*/
result = encrypt_data (data, &enc_params, &key, &tmp);
if (result < 0)
{
MHD_gnutls_assert ();
goto error;
}
/* write the encrypted data.
*/
result =
MHD__asn1_write_value (pkcs7_asn,
"encryptedContentInfo.encryptedContent", tmp.data,
tmp.size);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
MHD__gnutls_free_datum (&tmp);
MHD__gnutls_free_datum (&key);
/* Now write the rest of the pkcs-7 stuff.
*/
result = MHD__gnutls_x509_write_uint32 (pkcs7_asn, "version", 0);
if (result < 0)
{
MHD_gnutls_assert ();
goto error;
}
result =
MHD__asn1_write_value (pkcs7_asn, "encryptedContentInfo.contentType",
DATA_OID, 1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
result = MHD__asn1_write_value (pkcs7_asn, "unprotectedAttrs", NULL, 0);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
/* Now encode and copy the DER stuff.
*/
result = MHD__gnutls_x509_der_encode (pkcs7_asn, "", enc, 0);
MHD__asn1_delete_structure (&pkcs7_asn);
if (result < 0)
{
MHD_gnutls_assert ();
goto error;
}
error:
MHD__gnutls_free_datum (&key);
MHD__gnutls_free_datum (&tmp);
MHD__asn1_delete_structure (&pkcs7_asn);
return result;
}
#endif