This commit is contained in:
Christian Grothoff committed 2008-11-16 04:23:30 +00:00
1 parent a61b09be33
commit e81f372ed1
15 files changed
+1 -3874

No files matched your search

-4
View File
@@ -186,10 +186,6 @@ MHD__gnutls_certificate_free_credentials (MHD_gtls_cert_credentials_t sc)
MHD__gnutls_certificate_free_keys (sc);
MHD__gnutls_certificate_free_cas (sc);
MHD__gnutls_certificate_free_ca_names (sc);
#ifdef ENABLE_PKI
MHD__gnutls_certificate_free_crls (sc);
#endif
#ifdef KEYRING_HACK
MHD__gnutls_free_datum (&sc->keyring);
#endif
-232
View File
@@ -50,7 +50,6 @@
#include "x509.h"
#include "verify.h"
#include "mpi.h"
#include "pkcs7.h"
#include "privkey.h"
@@ -536,15 +535,6 @@ MHD__gnutls_x509_raw_privkey_to_gkey (MHD_gnutls_privkey * privkey,
}
ret = MHD_gnutls_x509_privkey_import (tmpkey, raw_key, type);
#ifdef ENABLE_PKI
/* If normal key decoding doesn't work try decoding a plain PKCS #8 key */
if (ret < 0)
ret =
MHD_gnutls_x509_privkey_import_pkcs8 (tmpkey, raw_key, type, NULL,
GNUTLS_PKCS_PLAIN);
#endif
if (ret < 0)
{
MHD_gnutls_assert ();
@@ -972,225 +962,3 @@ MHD__gnutls_certificate_set_x509_trust_mem (MHD_gtls_cert_credentials_t
return ret;
}
#ifdef ENABLE_PKI
static int
parse_pem_crl_mem (MHD_gnutls_x509_crl_t ** crl_list, unsigned *ncrls,
const opaque * input_crl, int input_crl_size)
{
int size, i;
const opaque *ptr;
MHD_gnutls_datum_t tmp;
int ret, count;
/* move to the certificate
*/
ptr = memmem (input_crl, input_crl_size,
PEM_CRL_SEP, sizeof (PEM_CRL_SEP) - 1);
if (ptr == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_BASE64_DECODING_ERROR;
}
size = input_crl_size - (ptr - input_crl);
i = *ncrls + 1;
count = 0;
do
{
*crl_list =
(MHD_gnutls_x509_crl_t *) MHD_gtls_realloc_fast (*crl_list,
i *
sizeof
(MHD_gnutls_x509_crl_t));
if (*crl_list == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_MEMORY_ERROR;
}
ret = MHD_gnutls_x509_crl_init (&crl_list[0][i - 1]);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
tmp.data = (unsigned char *) ptr;
tmp.size = size;
ret =
MHD_gnutls_x509_crl_import (crl_list[0][i - 1],
&tmp, GNUTLS_X509_FMT_PEM);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
/* now we move ptr after the pem header
*/
ptr++;
/* find the next certificate (if any)
*/
size = input_crl_size - (ptr - input_crl);
if (size > 0)
ptr = memmem (ptr, size, PEM_CRL_SEP, sizeof (PEM_CRL_SEP) - 1);
else
ptr = NULL;
i++;
count++;
}
while (ptr != NULL);
*ncrls = i - 1;
return count;
}
/* Reads a DER encoded certificate list from memory and stores it to
* a MHD_gnutls_cert structure.
* returns the number of certificates parsed.
*/
static int
parse_der_crl_mem (MHD_gnutls_x509_crl_t ** crl_list, unsigned *ncrls,
const void *input_crl, int input_crl_size)
{
int i;
MHD_gnutls_datum_t tmp;
int ret;
i = *ncrls + 1;
*crl_list =
(MHD_gnutls_x509_crl_t *) MHD_gtls_realloc_fast (*crl_list,
i *
sizeof
(MHD_gnutls_x509_crl_t));
if (*crl_list == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_MEMORY_ERROR;
}
tmp.data = (opaque *) input_crl;
tmp.size = input_crl_size;
ret = MHD_gnutls_x509_crl_init (&crl_list[0][i - 1]);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
ret =
MHD_gnutls_x509_crl_import (crl_list[0][i - 1], &tmp,
GNUTLS_X509_FMT_DER);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
*ncrls = i;
return 1; /* one certificate parsed */
}
/* Reads a DER or PEM CRL from memory
*/
static int
read_crl_mem (MHD_gtls_cert_credentials_t res, const void *crl,
int crl_size, MHD_gnutls_x509_crt_fmt_t type)
{
int ret;
/* allocate space for the certificate to add
*/
res->x509_crl_list = MHD_gtls_realloc_fast (res->x509_crl_list,
(1 +
res->x509_ncrls) *
sizeof (MHD_gnutls_x509_crl_t));
if (res->x509_crl_list == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_MEMORY_ERROR;
}
if (type == GNUTLS_X509_FMT_DER)
ret = parse_der_crl_mem (&res->x509_crl_list,
&res->x509_ncrls, crl, crl_size);
else
ret = parse_pem_crl_mem (&res->x509_crl_list,
&res->x509_ncrls, crl, crl_size);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
return ret;
}
/**
* MHD__gnutls_certificate_set_x509_crl_mem - Used to add CRLs in a MHD_gtls_cert_credentials_t structure
* @res: is an #MHD_gtls_cert_credentials_t structure.
* @CRL: is a list of trusted CRLs. They should have been verified before.
* @type: is DER or PEM
*
* This function adds the trusted CRLs in order to verify client or
* server certificates. In case of a client this is not required to
* be called if the certificates are not verified using
* MHD_gtls_certificate_verify_peers2(). This function may be called
* multiple times.
*
* Returns: number of CRLs processed, or a negative value on error.
**/
int
MHD__gnutls_certificate_set_x509_crl_mem (MHD_gtls_cert_credentials_t
res, const MHD_gnutls_datum_t * CRL,
MHD_gnutls_x509_crt_fmt_t type)
{
int ret;
if ((ret = read_crl_mem (res, CRL->data, CRL->size, type)) < 0)
return ret;
return ret;
}
/**
* 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.
*
* This function will delete all the CRLs associated
* with the given credentials.
*
**/
void
MHD__gnutls_certificate_free_crls (MHD_gtls_cert_credentials_t sc)
{
unsigned j;
for (j = 0; j < sc->x509_ncrls; j++)
{
MHD_gnutls_x509_crl_deinit (sc->x509_crl_list[j]);
}
sc->x509_ncrls = 0;
MHD_gnutls_free (sc->x509_crl_list);
sc->x509_crl_list = NULL;
}
#endif
+1 -5
View File
@@ -18,16 +18,12 @@ libx509_la_LDFLAGS = -lgcrypt
libx509_la_SOURCES = \
common.c common.h \
crl.c \
dn.c dn.h \
extensions.c extensions.h \
mpi.c mpi.h \
pkcs12_encr.c pkcs12.h \
pkcs7.c pkcs7.h \
pkcs12.h \
x509_privkey.c privkey.h \
privkey_pkcs8.c \
rfc2818_hostname.c rfc2818.h \
sign.c sign.h \
x509_verify.c verify.h \
x509.c x509.h
-437
View File
@@ -1,437 +0,0 @@
/*
* Copyright (C) 2003, 2004, 2005, 2006, 2007 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
*
*/
#include <gnutls_int.h>
#include <libtasn1.h>
#ifdef ENABLE_PKI
#include <gnutls_datum.h>
#include <gnutls_global.h>
#include <gnutls_errors.h>
#include <common.h>
#include <x509_b64.h>
#include <x509.h>
#include <dn.h>
/**
* MHD_gnutls_x509_crl_init - This function initializes a MHD_gnutls_x509_crl_t structure
* @crl: The structure to be initialized
*
* This function will initialize a CRL structure. CRL stands for
* Certificate Revocation List. A revocation list usually contains
* lists of certificate serial numbers that have been revoked
* by an Authority. The revocation lists are always signed with
* the authority's private key.
*
* Returns 0 on success.
*
**/
int
MHD_gnutls_x509_crl_init (MHD_gnutls_x509_crl_t * crl)
{
*crl = MHD_gnutls_calloc (1, sizeof (MHD_gnutls_x509_crl_int));
if (*crl)
{
int result = MHD__asn1_create_element (MHD__gnutls_get_pkix (),
"PKIX1.CertificateList",
&(*crl)->crl);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
MHD_gnutls_free (*crl);
return MHD_gtls_asn2err (result);
}
return 0; /* success */
}
return GNUTLS_E_MEMORY_ERROR;
}
/**
* MHD_gnutls_x509_crl_deinit - This function deinitializes memory used by a MHD_gnutls_x509_crl_t structure
* @crl: The structure to be initialized
*
* This function will deinitialize a CRL structure.
*
**/
void
MHD_gnutls_x509_crl_deinit (MHD_gnutls_x509_crl_t crl)
{
if (!crl)
return;
if (crl->crl)
MHD__asn1_delete_structure (&crl->crl);
MHD_gnutls_free (crl);
}
/**
* MHD_gnutls_x509_crl_import - This function will import a DER or PEM encoded CRL
* @crl: The structure to store the parsed CRL.
* @data: The DER or PEM encoded CRL.
* @format: One of DER or PEM
*
* This function will convert the given DER or PEM encoded CRL
* to the native MHD_gnutls_x509_crl_t format. The output will be stored in 'crl'.
*
* If the CRL is PEM encoded it should have a header of "X509 CRL".
*
* Returns 0 on success.
*
**/
int
MHD_gnutls_x509_crl_import (MHD_gnutls_x509_crl_t crl,
const MHD_gnutls_datum_t * data,
MHD_gnutls_x509_crt_fmt_t format)
{
int result = 0, need_free = 0;
MHD_gnutls_datum_t _data;
_data.data = data->data;
_data.size = data->size;
if (crl == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
/* If the CRL is in PEM format then decode it
*/
if (format == GNUTLS_X509_FMT_PEM)
{
opaque *out;
result =
MHD__gnutls_fbase64_decode (PEM_CRL, 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 (&crl->crl, _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_gnutls_x509_crl_get_signature_algorithm - This function returns the CRL's signature algorithm
* @crl: should contain a MHD_gnutls_x509_crl_t structure
*
* This function will return a value of the MHD_gnutls_sign_algorithm_t enumeration that
* is the signature algorithm.
*
* Returns a negative value on error.
*
**/
int
MHD_gnutls_x509_crl_get_signature_algorithm (MHD_gnutls_x509_crl_t crl)
{
int result;
MHD_gnutls_datum_t sa;
if (crl == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
/* Read the signature algorithm. Note that parameters are not
* read. They will be read from the issuer's certificate if needed.
*/
result =
MHD__gnutls_x509_read_value (crl->crl, "signatureAlgorithm.algorithm",
&sa, 0);
if (result < 0)
{
MHD_gnutls_assert ();
return result;
}
result = MHD_gtls_x509_oid2sign_algorithm ((const char *) sa.data);
MHD__gnutls_free_datum (&sa);
return result;
}
/**
* MHD_gnutls_x509_crl_get_signature - Returns the CRL's signature
* @crl: should contain a MHD_gnutls_x509_crl_t structure
* @sig: a pointer where the signature part will be copied (may be null).
* @sizeof_sig: initially holds the size of @sig
*
* This function will extract the signature field of a CRL.
*
* Returns 0 on success, and a negative value on error.
**/
int
MHD_gnutls_x509_crl_get_signature (MHD_gnutls_x509_crl_t crl,
char *sig, size_t * sizeof_sig)
{
int result;
int bits, len;
if (crl == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
bits = 0;
result = MHD__asn1_read_value (crl->crl, "signature", NULL, &bits);
if (result != ASN1_MEM_ERROR)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
if (bits % 8 != 0)
{
MHD_gnutls_assert ();
return GNUTLS_E_CERTIFICATE_ERROR;
}
len = bits / 8;
if (*sizeof_sig < len)
{
*sizeof_sig = bits / 8;
return GNUTLS_E_SHORT_MEMORY_BUFFER;
}
result = MHD__asn1_read_value (crl->crl, "signature", sig, &len);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
return 0;
}
/**
* MHD_gnutls_x509_crl_get_crt_count - This function returns the number of revoked certificates in a CRL
* @crl: should contain a MHD_gnutls_x509_crl_t structure
*
* This function will return the number of revoked certificates in the
* given CRL.
*
* Returns a negative value on failure.
*
**/
int
MHD_gnutls_x509_crl_get_crt_count (MHD_gnutls_x509_crl_t crl)
{
int count, result;
if (crl == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
result =
MHD__asn1_number_of_elements (crl->crl,
"tbsCertList.revokedCertificates", &count);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return 0; /* no certificates */
}
return count;
}
/**
* MHD_gnutls_x509_crl_get_crt_serial - This function returns the serial number of a revoked certificate
* @crl: should contain a MHD_gnutls_x509_crl_t structure
* @indx: the index of the certificate to extract (starting from 0)
* @serial: where the serial number will be copied
* @serial_size: initially holds the size of serial
* @t: if non null, will hold the time this certificate was revoked
*
* This function will return the serial number of the specified, by
* the index, revoked certificate.
*
* Returns a negative value on failure.
*
**/
int
MHD_gnutls_x509_crl_get_crt_serial (MHD_gnutls_x509_crl_t crl, int indx,
unsigned char *serial,
size_t * serial_size, time_t * t)
{
int result, _serial_size;
char serial_name[MAX_NAME_SIZE];
char date_name[MAX_NAME_SIZE];
if (crl == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
snprintf (serial_name, sizeof (serial_name),
"tbsCertList.revokedCertificates.?%u.userCertificate", indx + 1);
snprintf (date_name, sizeof (date_name),
"tbsCertList.revokedCertificates.?%u.revocationDate", indx + 1);
_serial_size = *serial_size;
result =
MHD__asn1_read_value (crl->crl, serial_name, serial, &_serial_size);
*serial_size = _serial_size;
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
if (result == ASN1_ELEMENT_NOT_FOUND)
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
return MHD_gtls_asn2err (result);
}
if (t)
{
*t = MHD__gnutls_x509_get_time (crl->crl, date_name);
}
return 0;
}
/*-
* MHD__gnutls_x509_crl_get_raw_issuer_dn - This function returns the issuer's DN DER encoded
* @crl: should contain a MHD_gnutls_x509_crl_t structure
* @dn: will hold the starting point of the DN
*
* This function will return a pointer to the DER encoded DN structure and
* the length.
*
* Returns a negative value on error, and zero on success.
*
-*/
int
MHD__gnutls_x509_crl_get_raw_issuer_dn (MHD_gnutls_x509_crl_t crl,
MHD_gnutls_datum_t * dn)
{
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
int result, len1;
int start1, end1;
MHD_gnutls_datum_t crl_signed_data;
if (crl == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
/* get the issuer of 'crl'
*/
if ((result =
MHD__asn1_create_element (MHD__gnutls_get_pkix (), "PKIX1.TBSCertList",
&c2)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
result =
MHD__gnutls_x509_get_signed_data (crl->crl, "tbsCertList",
&crl_signed_data);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
result =
MHD__asn1_der_decoding (&c2, crl_signed_data.data, crl_signed_data.size,
NULL);
if (result != ASN1_SUCCESS)
{
/* couldn't decode DER */
MHD_gnutls_assert ();
MHD__asn1_delete_structure (&c2);
result = MHD_gtls_asn2err (result);
goto cleanup;
}
result =
MHD__asn1_der_decoding_startEnd (c2, crl_signed_data.data,
crl_signed_data.size, "issuer",
&start1, &end1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
len1 = end1 - start1 + 1;
MHD__gnutls_set_datum (dn, &crl_signed_data.data[start1], len1);
result = 0;
cleanup:
MHD__asn1_delete_structure (&c2);
MHD__gnutls_free_datum (&crl_signed_data);
return result;
}
#endif
-317
View File
@@ -83,126 +83,6 @@ MHD__gnutls_x509_read_rsa_params (opaque * der, int dersize, mpi_t * params)
}
/* reads p,q and g
* from the certificate (subjectPublicKey BIT STRING).
* params[0-2]
*/
int
MHD__gnutls_x509_read_dsa_params (opaque * der, int dersize, mpi_t * params)
{
int result;
ASN1_TYPE spk = ASN1_TYPE_EMPTY;
if ((result =
MHD__asn1_create_element (MHD__gnutls_get_pkix (), "PKIX1.Dss-Parms",
&spk)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
result = MHD__asn1_der_decoding (&spk, der, dersize, NULL);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
MHD__asn1_delete_structure (&spk);
return MHD_gtls_asn2err (result);
}
/* FIXME: If the parameters are not included in the certificate
* then the issuer's parameters should be used. This is not
* done yet.
*/
/* Read p */
if ((result = MHD__gnutls_x509_read_int (spk, "p", &params[0])) < 0)
{
MHD_gnutls_assert ();
MHD__asn1_delete_structure (&spk);
return GNUTLS_E_ASN1_GENERIC_ERROR;
}
/* Read q */
if ((result = MHD__gnutls_x509_read_int (spk, "q", &params[1])) < 0)
{
MHD_gnutls_assert ();
MHD__asn1_delete_structure (&spk);
MHD_gtls_mpi_release (&params[0]);
return GNUTLS_E_ASN1_GENERIC_ERROR;
}
/* Read g */
if ((result = MHD__gnutls_x509_read_int (spk, "g", &params[2])) < 0)
{
MHD_gnutls_assert ();
MHD__asn1_delete_structure (&spk);
MHD_gtls_mpi_release (&params[0]);
MHD_gtls_mpi_release (&params[1]);
return GNUTLS_E_ASN1_GENERIC_ERROR;
}
MHD__asn1_delete_structure (&spk);
return 0;
}
/* Reads an Integer from the DER encoded data
*/
int
MHD__gnutls_x509_read_der_int (opaque * der, int dersize, mpi_t * out)
{
int result;
ASN1_TYPE spk = ASN1_TYPE_EMPTY;
/* == INTEGER */
if ((result =
MHD__asn1_create_element (MHD__gnutls_getMHD__gnutls_asn (),
"GNUTLS.DSAPublicKey",
&spk)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
result = MHD__asn1_der_decoding (&spk, der, dersize, NULL);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
MHD__asn1_delete_structure (&spk);
return MHD_gtls_asn2err (result);
}
/* Read Y */
if ((result = MHD__gnutls_x509_read_int (spk, "", out)) < 0)
{
MHD_gnutls_assert ();
MHD__asn1_delete_structure (&spk);
return MHD_gtls_asn2err (result);
}
MHD__asn1_delete_structure (&spk);
return 0;
}
/* reads DSA's Y
* from the certificate
* only sets params[3]
*/
int
MHD__gnutls_x509_read_dsa_pubkey (opaque * der, int dersize, mpi_t * params)
{
return MHD__gnutls_x509_read_der_int (der, dersize, &params[3]);
}
/* Extracts DSA and RSA parameters from a certificate.
*/
@@ -331,181 +211,6 @@ cleanup:MHD__asn1_delete_structure (&spk);
return result;
}
/*
* This function writes and encodes the parameters for DSS or RSA keys.
* This is the "signatureAlgorithm" fields.
*/
int
MHD__gnutls_x509_write_sig_params (ASN1_TYPE dst,
const char *dst_name,
enum MHD_GNUTLS_PublicKeyAlgorithm
pk_algorithm,
enum MHD_GNUTLS_HashAlgorithm dig,
mpi_t * params, int params_size)
{
int result;
char name[128];
const char *pk;
MHD_gtls_str_cpy (name, sizeof (name), dst_name);
MHD_gtls_str_cat (name, sizeof (name), ".algorithm");
pk = MHD_gtls_x509_sign_to_oid (pk_algorithm, HASH2MAC (dig));
if (pk == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
/* write the OID.
*/
result = MHD__asn1_write_value (dst, name, pk, 1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
MHD_gtls_str_cpy (name, sizeof (name), dst_name);
MHD_gtls_str_cat (name, sizeof (name), ".parameters");
if (pk_algorithm == MHD_GNUTLS_PK_RSA)
{ /* RSA */
result = MHD__asn1_write_value (dst, name, NULL, 0);
if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND)
{
/* Here we ignore the element not found error, since this
* may have been disabled before.
*/
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
}
return 0;
}
/*
* This function writes the parameters for DSS keys.
* Needs 3 parameters (p,q,g).
*
* Allocates the space used to store the DER data.
*/
int
MHD__gnutls_x509_write_dsa_params (mpi_t * params,
int params_size, MHD_gnutls_datum_t * der)
{
int result;
ASN1_TYPE spk = ASN1_TYPE_EMPTY;
der->data = NULL;
der->size = 0;
if (params_size < 3)
{
MHD_gnutls_assert ();
result = GNUTLS_E_INVALID_REQUEST;
goto cleanup;
}
if ((result =
MHD__asn1_create_element (MHD__gnutls_getMHD__gnutls_asn (),
"GNUTLS.DSAParameters",
&spk)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
result = MHD__gnutls_x509_write_int (spk, "p", params[0], 0);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
result = MHD__gnutls_x509_write_int (spk, "q", params[1], 0);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
result = MHD__gnutls_x509_write_int (spk, "g", params[2], 0);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
result = MHD__gnutls_x509_der_encode (spk, "", der, 0);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
result = 0;
cleanup:MHD__asn1_delete_structure (&spk);
return result;
}
/*
* This function writes the public parameters for DSS keys.
* Needs 1 parameter (y).
*
* Allocates the space used to store the DER data.
*/
int
MHD__gnutls_x509_write_dsa_public_key (mpi_t * params,
int params_size,
MHD_gnutls_datum_t * der)
{
int result;
ASN1_TYPE spk = ASN1_TYPE_EMPTY;
der->data = NULL;
der->size = 0;
if (params_size < 3)
{
MHD_gnutls_assert ();
result = GNUTLS_E_INVALID_REQUEST;
goto cleanup;
}
if ((result =
MHD__asn1_create_element (MHD__gnutls_getMHD__gnutls_asn (),
"GNUTLS.DSAPublicKey",
&spk)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
result = MHD__gnutls_x509_write_int (spk, "", params[3], 0);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
result = MHD__gnutls_x509_der_encode (spk, "", der, 0);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
MHD__asn1_delete_structure (&spk);
return 0;
cleanup:MHD__asn1_delete_structure (&spk);
return result;
}
/* this function reads a (small) unsigned integer
* from asn1 structs. Combines the read and the convertion
* steps.
@@ -560,25 +265,3 @@ MHD__gnutls_x509_read_uint (ASN1_TYPE node, const char *value,
return 0;
}
/* Writes the specified integer into the specified node.
*/
int
MHD__gnutls_x509_write_uint32 (ASN1_TYPE node, const char *value,
uint32_t num)
{
opaque tmpstr[4];
int result;
MHD_gtls_write_uint32 (num, tmpstr);
result = MHD__asn1_write_value (node, value, tmpstr, 4);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
return 0;
}
-19
View File
@@ -29,32 +29,13 @@ int MHD__gnutls_x509_crt_get_mpis (MHD_gnutls_x509_crt_t cert,
mpi_t * params, int *params_size);
int MHD__gnutls_x509_read_rsa_params (opaque * der, int dersize,
mpi_t * params);
int MHD__gnutls_x509_read_dsa_pubkey (opaque * der, int dersize,
mpi_t * params);
int MHD__gnutls_x509_read_dsa_params (opaque * der, int dersize,
mpi_t * params);
int MHD__gnutls_x509_write_rsa_params (mpi_t * params, int params_size,
MHD_gnutls_datum_t * der);
int MHD__gnutls_x509_write_dsa_params (mpi_t * params, int params_size,
MHD_gnutls_datum_t * der);
int MHD__gnutls_x509_write_dsa_public_key (mpi_t * params, int params_size,
MHD_gnutls_datum_t * der);
int MHD__gnutls_x509_read_uint (ASN1_TYPE node, const char *value,
unsigned int *ret);
int MHD__gnutls_x509_read_der_int (opaque * der, int dersize, mpi_t * out);
int MHD__gnutls_x509_read_int (ASN1_TYPE node, const char *value,
mpi_t * ret_mpi);
int MHD__gnutls_x509_write_int (ASN1_TYPE node, const char *value, mpi_t mpi,
int lz);
int MHD__gnutls_x509_write_uint32 (ASN1_TYPE node, const char *value,
uint32_t num);
int MHD__gnutls_x509_write_sig_params (ASN1_TYPE dst, const char *dst_name,
enum MHD_GNUTLS_PublicKeyAlgorithm
pk_algorithm,
enum MHD_GNUTLS_HashAlgorithm,
mpi_t * params, int params_size);
-169
View File
@@ -1,169 +0,0 @@
/* minip12.c - A mini pkcs-12 implementation (modified for gnutls)
*
* Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
*
* 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
*
*/
#include <gnutls_int.h>
#ifdef ENABLE_PKI
#include <gcrypt.h>
#include <gc.h>
#include <gnutls_errors.h>
/* Returns 0 if the password is ok, or a negative error
* code instead.
*/
static int
MHD_pkcs12_check_pass (const char *pass, size_t plen)
{
const char *p = pass;
unsigned int i;
for (i = 0; i < plen; i++)
{
if (isascii (p[i]))
continue;
return GNUTLS_E_INVALID_PASSWORD;
}
return 0;
}
/* ID should be:
* 3 for MAC
* 2 for IV
* 1 for encryption key
*/
int
MHD_pkcs12_string_to_key (unsigned int id, const opaque * salt,
unsigned int salt_size, unsigned int iter,
const char *pw, unsigned int req_keylen,
opaque * keybuf)
{
int rc;
unsigned int i, j;
MHD_gc_hash_handle md;
mpi_t num_b1 = NULL;
unsigned int pwlen;
opaque hash[20], buf_b[64], buf_i[128], *p;
size_t cur_keylen;
size_t n;
cur_keylen = 0;
if (pw == NULL)
pwlen = 0;
else
pwlen = strlen (pw);
if (pwlen > 63 / 2)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
if ((rc = MHD_pkcs12_check_pass (pw, pwlen)) < 0)
{
MHD_gnutls_assert ();
return rc;
}
/* Store salt and password in BUF_I */
p = buf_i;
for (i = 0; i < 64; i++)
*p++ = salt[i % salt_size];
if (pw)
{
for (i = j = 0; i < 64; i += 2)
{
*p++ = 0;
*p++ = pw[j];
if (++j > pwlen) /* Note, that we include the trailing zero */
j = 0;
}
}
else
memset (p, 0, 64);
for (;;)
{
rc = MHD_gc_hash_open (GC_SHA1, 0, &md);
if (rc)
{
MHD_gnutls_assert ();
return GNUTLS_E_DECRYPTION_FAILED;
}
for (i = 0; i < 64; i++)
{
unsigned char lid = id & 0xFF;
MHD_gc_hash_write (md, 1, (const char *) &lid);
}
MHD_gc_hash_write (md, pw ? 128 : 64, (const char *) buf_i);
memcpy (hash, MHD_gc_hash_read (md), 20);
MHD_gc_hash_close (md);
for (i = 1; i < iter; i++)
MHD_gc_hash_buffer (GC_SHA1, hash, 20, (char *) hash);
for (i = 0; i < 20 && cur_keylen < req_keylen; i++)
keybuf[cur_keylen++] = hash[i];
if (cur_keylen == req_keylen)
{
gcry_mpi_release (num_b1);
return 0; /* ready */
}
/* need more bytes. */
for (i = 0; i < 64; i++)
buf_b[i] = hash[i % 20];
n = 64;
rc = MHD_gtls_mpi_scan (&num_b1, buf_b, &n);
if (rc < 0)
{
MHD_gnutls_assert ();
return rc;
}
gcry_mpi_add_ui (num_b1, num_b1, 1);
for (i = 0; i < 128; i += 64)
{
mpi_t num_ij;
n = 64;
rc = MHD_gtls_mpi_scan (&num_ij, buf_i + i, &n);
if (rc < 0)
{
MHD_gnutls_assert ();
return rc;
}
gcry_mpi_add (num_ij, num_ij, num_b1);
gcry_mpi_clear_highbit (num_ij, 64 * 8);
n = 64;
rc = MHD_gtls_mpi_print (buf_i + i, &n, num_ij);
if (rc < 0)
{
MHD_gnutls_assert ();
return rc;
}
gcry_mpi_release (num_ij);
}
}
}
#endif /* ENABLE_PKI */
-1029
View File
@@ -1,1029 +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 PKCS7 certificate lists parsing.
*/
#include <gnutls_int.h>
#include <libtasn1.h>
#ifdef ENABLE_PKI
#include <gnutls_datum.h>
#include <gnutls_global.h>
#include <gnutls_errors.h>
#include <common.h>
#include <x509_b64.h>
#include <pkcs7.h>
#include <dn.h>
#define SIGNED_DATA_OID "1.2.840.113549.1.7.2"
/* Decodes the PKCS #7 signed data, and returns an ASN1_TYPE,
* which holds them. If raw is non null then the raw decoded
* data are copied (they are locally allocated) there.
*/
static int
_decode_pkcs7_signed_data (ASN1_TYPE pkcs7, ASN1_TYPE * sdata,
MHD_gnutls_datum_t * raw)
{
char oid[128];
ASN1_TYPE c2;
opaque *tmp = NULL;
int tmp_size, len, result;
len = sizeof (oid) - 1;
result = MHD__asn1_read_value (pkcs7, "contentType", oid, &len);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
if (strcmp (oid, SIGNED_DATA_OID) != 0)
{
MHD_gnutls_assert ();
MHD__gnutls_x509_log ("Unknown PKCS7 Content OID '%s'\n", oid);
return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE;
}
if ((result = MHD__asn1_create_element
(MHD__gnutls_get_pkix (), "PKIX1.pkcs-7-SignedData",
&c2)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
/* the Signed-data has been created, so
* decode them.
*/
tmp_size = 0;
result = MHD__asn1_read_value (pkcs7, "content", NULL, &tmp_size);
if (result != ASN1_MEM_ERROR)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
tmp = MHD_gnutls_malloc (tmp_size);
if (tmp == NULL)
{
MHD_gnutls_assert ();
result = GNUTLS_E_MEMORY_ERROR;
goto cleanup;
}
result = MHD__asn1_read_value (pkcs7, "content", tmp, &tmp_size);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
/* tmp, tmp_size hold the data and the size of the CertificateSet structure
* actually the ANY stuff.
*/
/* Step 1. In case of a signed structure extract certificate set.
*/
result = MHD__asn1_der_decoding (&c2, tmp, tmp_size, NULL);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
if (raw == NULL)
{
MHD_gnutls_free (tmp);
}
else
{
raw->data = tmp;
raw->size = tmp_size;
}
*sdata = c2;
return 0;
cleanup:
if (c2)
MHD__asn1_delete_structure (&c2);
MHD_gnutls_free (tmp);
return result;
}
/**
* MHD_gnutls_pkcs7_init - This function initializes a MHD_gnutls_pkcs7_t structure
* @pkcs7: The structure to be initialized
*
* This function will initialize a PKCS7 structure. PKCS7 structures
* usually contain lists of X.509 Certificates and X.509 Certificate
* revocation lists.
*
* Returns 0 on success.
*
**/
int
MHD_gnutls_pkcs7_init (MHD_gnutls_pkcs7_t * pkcs7)
{
*pkcs7 = MHD_gnutls_calloc (1, sizeof (MHD_gnutls_pkcs7_int));
if (*pkcs7)
{
int result = MHD__asn1_create_element (MHD__gnutls_get_pkix (),
"PKIX1.pkcs-7-ContentInfo",
&(*pkcs7)->pkcs7);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
MHD_gnutls_free (*pkcs7);
return MHD_gtls_asn2err (result);
}
return 0; /* success */
}
return GNUTLS_E_MEMORY_ERROR;
}
/**
* MHD_gnutls_pkcs7_deinit - This function deinitializes memory used by a MHD_gnutls_pkcs7_t structure
* @pkcs7: The structure to be initialized
*
* This function will deinitialize a PKCS7 structure.
*
**/
void
MHD_gnutls_pkcs7_deinit (MHD_gnutls_pkcs7_t pkcs7)
{
if (!pkcs7)
return;
if (pkcs7->pkcs7)
MHD__asn1_delete_structure (&pkcs7->pkcs7);
MHD_gnutls_free (pkcs7);
}
/**
* MHD_gnutls_pkcs7_import - This function will import a DER or PEM encoded PKCS7
* @pkcs7: The structure to store the parsed PKCS7.
* @data: The DER or PEM encoded PKCS7.
* @format: One of DER or PEM
*
* This function will convert the given DER or PEM encoded PKCS7
* to the native MHD_gnutls_pkcs7_t format. The output will be stored in 'pkcs7'.
*
* If the PKCS7 is PEM encoded it should have a header of "PKCS7".
*
* Returns 0 on success.
*
**/
int
MHD_gnutls_pkcs7_import (MHD_gnutls_pkcs7_t pkcs7,
const MHD_gnutls_datum_t * data,
MHD_gnutls_x509_crt_fmt_t format)
{
int result = 0, need_free = 0;
MHD_gnutls_datum_t _data;
if (pkcs7 == NULL)
return GNUTLS_E_INVALID_REQUEST;
_data.data = data->data;
_data.size = data->size;
/* If the PKCS7 is in PEM format then decode it
*/
if (format == GNUTLS_X509_FMT_PEM)
{
opaque *out;
result = MHD__gnutls_fbase64_decode (PEM_PKCS7, 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 (&pkcs7->pkcs7, _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_gnutls_pkcs7_get_crt_raw - This function returns a certificate in a PKCS7 certificate set
* @pkcs7_struct: should contain a MHD_gnutls_pkcs7_t structure
* @indx: contains the index of the certificate to extract
* @certificate: the contents of the certificate will be copied there (may be null)
* @certificate_size: should hold the size of the certificate
*
* This function will return a certificate of the PKCS7 or RFC2630 certificate set.
* Returns 0 on success. If the provided buffer is not long enough,
* then @certificate_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER is returned.
*
* After the last certificate has been read GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
* will be returned.
*
**/
int
MHD_gnutls_pkcs7_get_crt_raw (MHD_gnutls_pkcs7_t pkcs7,
int indx, void *certificate,
size_t * certificate_size)
{
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
int result, len;
char root2[MAX_NAME_SIZE];
char oid[128];
MHD_gnutls_datum_t tmp = { NULL, 0 };
if (certificate_size == NULL || pkcs7 == NULL)
return GNUTLS_E_INVALID_REQUEST;
/* Step 1. decode the signed data.
*/
result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, &tmp);
if (result < 0)
{
MHD_gnutls_assert ();
return result;
}
/* Step 2. Parse the CertificateSet
*/
snprintf (root2, sizeof (root2), "certificates.?%u", indx + 1);
len = sizeof (oid) - 1;
result = MHD__asn1_read_value (c2, root2, oid, &len);
if (result == ASN1_VALUE_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;
}
/* if 'Certificate' is the choice found:
*/
if (strcmp (oid, "certificate") == 0)
{
int start, end;
result = MHD__asn1_der_decoding_startEnd (c2, tmp.data, tmp.size,
root2, &start, &end);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
end = end - start + 1;
if ((unsigned) end > *certificate_size)
{
*certificate_size = end;
result = GNUTLS_E_SHORT_MEMORY_BUFFER;
goto cleanup;
}
if (certificate)
memcpy (certificate, &tmp.data[start], end);
*certificate_size = end;
result = 0;
}
else
{
result = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
}
cleanup:
MHD__gnutls_free_datum (&tmp);
if (c2)
MHD__asn1_delete_structure (&c2);
return result;
}
/**
* MHD_gnutls_pkcs7_get_crt_count - This function returns the number of certificates in a PKCS7 certificate set
* @pkcs7_struct: should contain a MHD_gnutls_pkcs7_t structure
*
* This function will return the number of certifcates in the PKCS7 or
* RFC2630 certificate set.
*
* Returns a negative value on failure.
*
**/
int
MHD_gnutls_pkcs7_get_crt_count (MHD_gnutls_pkcs7_t pkcs7)
{
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
int result, count;
if (pkcs7 == NULL)
return GNUTLS_E_INVALID_REQUEST;
/* Step 1. decode the signed data.
*/
result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
if (result < 0)
{
MHD_gnutls_assert ();
return result;
}
/* Step 2. Count the CertificateSet */
result = MHD__asn1_number_of_elements (c2, "certificates", &count);
MHD__asn1_delete_structure (&c2);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return 0; /* no certificates */
}
return count;
}
/**
* MHD_gnutls_pkcs7_export - This function will export the pkcs7 structure
* @pkcs7: Holds the pkcs7 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 pkcs7 structure to DER or PEM format.
*
* If the buffer provided is not long enough to hold the output, then
* *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will
* be returned.
*
* If the structure is PEM encoded, it will have a header
* of "BEGIN PKCS7".
*
* Return value: In case of failure a negative value will be
* returned, and 0 on success.
*
**/
int
MHD_gnutls_pkcs7_export (MHD_gnutls_pkcs7_t pkcs7,
MHD_gnutls_x509_crt_fmt_t format, void *output_data,
size_t * output_data_size)
{
if (pkcs7 == NULL)
return GNUTLS_E_INVALID_REQUEST;
return MHD__gnutls_x509_export_int (pkcs7->pkcs7, format, PEM_PKCS7,
output_data, output_data_size);
}
/* Creates an empty signed data structure in the pkcs7
* structure and returns a handle to the signed data.
*/
static int
create_empty_signed_data (ASN1_TYPE pkcs7, ASN1_TYPE * sdata)
{
uint8_t one = 1;
int result;
*sdata = ASN1_TYPE_EMPTY;
if ((result = MHD__asn1_create_element
(MHD__gnutls_get_pkix (), "PKIX1.pkcs-7-SignedData",
sdata)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
/* Use version 1
*/
result = MHD__asn1_write_value (*sdata, "version", &one, 1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
/* Use no digest algorithms
*/
/* id-data */
result =
MHD__asn1_write_value (*sdata, "encapContentInfo.eContentType",
"1.2.840.113549.1.7.5", 1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
result =
MHD__asn1_write_value (*sdata, "encapContentInfo.eContent", NULL, 0);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
/* Add no certificates.
*/
/* Add no crls.
*/
/* Add no signerInfos.
*/
/* Write the content type of the signed data
*/
result = MHD__asn1_write_value (pkcs7, "contentType", SIGNED_DATA_OID, 1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
return 0;
cleanup:
MHD__asn1_delete_structure (sdata);
return result;
}
/**
* MHD_gnutls_pkcs7_set_crt_raw - This function adds a certificate in a PKCS7 certificate set
* @pkcs7_struct: should contain a MHD_gnutls_pkcs7_t structure
* @crt: the DER encoded certificate to be added
*
* This function will add a certificate to the PKCS7 or RFC2630 certificate set.
* Returns 0 on success.
*
**/
int
MHD_gnutls_pkcs7_set_crt_raw (MHD_gnutls_pkcs7_t pkcs7,
const MHD_gnutls_datum_t * crt)
{
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
int result;
if (pkcs7 == NULL)
return GNUTLS_E_INVALID_REQUEST;
/* Step 1. decode the signed data.
*/
result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
if (result < 0 && result != GNUTLS_E_ASN1_VALUE_NOT_FOUND)
{
MHD_gnutls_assert ();
return result;
}
/* If the signed data are uninitialized
* then create them.
*/
if (result == GNUTLS_E_ASN1_VALUE_NOT_FOUND)
{
/* The pkcs7 structure is new, so create the
* signedData.
*/
result = create_empty_signed_data (pkcs7->pkcs7, &c2);
if (result < 0)
{
MHD_gnutls_assert ();
return result;
}
}
/* Step 2. Append the new certificate.
*/
result = MHD__asn1_write_value (c2, "certificates", "NEW", 1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
result = MHD__asn1_write_value (c2, "certificates.?LAST", "certificate", 1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
result =
MHD__asn1_write_value (c2, "certificates.?LAST.certificate", crt->data,
crt->size);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
/* Step 3. Replace the old content with the new
*/
result =
MHD__gnutls_x509_der_encode_and_copy (c2, "", pkcs7->pkcs7, "content", 0);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
MHD__asn1_delete_structure (&c2);
return 0;
cleanup:
if (c2)
MHD__asn1_delete_structure (&c2);
return result;
}
/**
* MHD_gnutls_pkcs7_set_crt - This function adds a parsed certificate in a PKCS7 certificate set
* @pkcs7_struct: should contain a MHD_gnutls_pkcs7_t structure
* @crt: the certificate to be copied.
*
* This function will add a parsed certificate to the PKCS7 or RFC2630 certificate set.
* This is a wrapper function over MHD_gnutls_pkcs7_set_crt_raw() .
*
* Returns 0 on success.
*
**/
int
MHD_gnutls_pkcs7_set_crt (MHD_gnutls_pkcs7_t pkcs7, MHD_gnutls_x509_crt_t crt)
{
int ret;
MHD_gnutls_datum_t data;
if (pkcs7 == NULL)
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_gnutls_pkcs7_set_crt_raw (pkcs7, &data);
MHD__gnutls_free_datum (&data);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
return 0;
}
/**
* MHD_gnutls_pkcs7_delete_crt - This function deletes a certificate from a PKCS7 certificate set
* @pkcs7_struct: should contain a MHD_gnutls_pkcs7_t structure
* @indx: the index of the certificate to delete
*
* This function will delete a certificate from a PKCS7 or RFC2630 certificate set.
* Index starts from 0. Returns 0 on success.
*
**/
int
MHD_gnutls_pkcs7_delete_crt (MHD_gnutls_pkcs7_t pkcs7, int indx)
{
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
int result;
char root2[MAX_NAME_SIZE];
if (pkcs7 == NULL)
return GNUTLS_E_INVALID_REQUEST;
/* Step 1. Decode the signed data.
*/
result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
if (result < 0)
{
MHD_gnutls_assert ();
return result;
}
/* Step 2. Delete the certificate.
*/
snprintf (root2, sizeof (root2), "certificates.?%u", indx + 1);
result = MHD__asn1_write_value (c2, root2, NULL, 0);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
/* Step 3. Replace the old content with the new
*/
result =
MHD__gnutls_x509_der_encode_and_copy (c2, "", pkcs7->pkcs7, "content", 0);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
MHD__asn1_delete_structure (&c2);
return 0;
cleanup:
if (c2)
MHD__asn1_delete_structure (&c2);
return result;
}
/* Read and write CRLs
*/
/**
* MHD_gnutls_pkcs7_get_crl_raw - This function returns a crl in a PKCS7 crl set
* @pkcs7_struct: should contain a MHD_gnutls_pkcs7_t structure
* @indx: contains the index of the crl to extract
* @crl: the contents of the crl will be copied there (may be null)
* @crl_size: should hold the size of the crl
*
* This function will return a crl of the PKCS7 or RFC2630 crl set.
* Returns 0 on success. If the provided buffer is not long enough,
* then @crl_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER is returned.
*
* After the last crl has been read GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
* will be returned.
*
**/
int
MHD_gnutls_pkcs7_get_crl_raw (MHD_gnutls_pkcs7_t pkcs7,
int indx, void *crl, size_t * crl_size)
{
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
int result;
char root2[MAX_NAME_SIZE];
MHD_gnutls_datum_t tmp = { NULL, 0 };
int start, end;
if (pkcs7 == NULL || crl_size == NULL)
return GNUTLS_E_INVALID_REQUEST;
/* Step 1. decode the signed data.
*/
result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, &tmp);
if (result < 0)
{
MHD_gnutls_assert ();
return result;
}
/* Step 2. Parse the CertificateSet
*/
snprintf (root2, sizeof (root2), "crls.?%u", indx + 1);
/* Get the raw CRL
*/
result = MHD__asn1_der_decoding_startEnd (c2, tmp.data, tmp.size,
root2, &start, &end);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
end = end - start + 1;
if ((unsigned) end > *crl_size)
{
*crl_size = end;
result = GNUTLS_E_SHORT_MEMORY_BUFFER;
goto cleanup;
}
if (crl)
memcpy (crl, &tmp.data[start], end);
*crl_size = end;
result = 0;
cleanup:
MHD__gnutls_free_datum (&tmp);
if (c2)
MHD__asn1_delete_structure (&c2);
return result;
}
/**
* MHD_gnutls_pkcs7_get_crl_count - This function returns the number of crls in a PKCS7 crl set
* @pkcs7_struct: should contain a MHD_gnutls_pkcs7_t structure
*
* This function will return the number of certifcates in the PKCS7 or
* RFC2630 crl set.
*
* Returns a negative value on failure.
*
**/
int
MHD_gnutls_pkcs7_get_crl_count (MHD_gnutls_pkcs7_t pkcs7)
{
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
int result, count;
if (pkcs7 == NULL)
return GNUTLS_E_INVALID_REQUEST;
/* Step 1. decode the signed data.
*/
result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
if (result < 0)
{
MHD_gnutls_assert ();
return result;
}
/* Step 2. Count the CertificateSet */
result = MHD__asn1_number_of_elements (c2, "crls", &count);
MHD__asn1_delete_structure (&c2);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return 0; /* no crls */
}
return count;
}
/**
* MHD_gnutls_pkcs7_set_crl_raw - This function adds a crl in a PKCS7 crl set
* @pkcs7_struct: should contain a MHD_gnutls_pkcs7_t structure
* @crl: the DER encoded crl to be added
*
* This function will add a crl to the PKCS7 or RFC2630 crl set.
* Returns 0 on success.
*
**/
int
MHD_gnutls_pkcs7_set_crl_raw (MHD_gnutls_pkcs7_t pkcs7,
const MHD_gnutls_datum_t * crl)
{
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
int result;
if (pkcs7 == NULL)
return GNUTLS_E_INVALID_REQUEST;
/* Step 1. decode the signed data.
*/
result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
if (result < 0 && result != GNUTLS_E_ASN1_VALUE_NOT_FOUND)
{
MHD_gnutls_assert ();
return result;
}
/* If the signed data are uninitialized
* then create them.
*/
if (result == GNUTLS_E_ASN1_VALUE_NOT_FOUND)
{
/* The pkcs7 structure is new, so create the
* signedData.
*/
result = create_empty_signed_data (pkcs7->pkcs7, &c2);
if (result < 0)
{
MHD_gnutls_assert ();
return result;
}
}
/* Step 2. Append the new crl.
*/
result = MHD__asn1_write_value (c2, "crls", "NEW", 1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
result = MHD__asn1_write_value (c2, "crls.?LAST", crl->data, crl->size);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
/* Step 3. Replace the old content with the new
*/
result =
MHD__gnutls_x509_der_encode_and_copy (c2, "", pkcs7->pkcs7, "content", 0);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
MHD__asn1_delete_structure (&c2);
return 0;
cleanup:
if (c2)
MHD__asn1_delete_structure (&c2);
return result;
}
/**
* MHD_gnutls_pkcs7_set_crl - This function adds a parsed crl in a PKCS7 crl set
* @pkcs7_struct: should contain a MHD_gnutls_pkcs7_t structure
* @crl: the DER encoded crl to be added
*
* This function will add a parsed crl to the PKCS7 or RFC2630 crl set.
* Returns 0 on success.
*
**/
int
MHD_gnutls_pkcs7_set_crl (MHD_gnutls_pkcs7_t pkcs7, MHD_gnutls_x509_crl_t crl)
{
int ret;
MHD_gnutls_datum_t data;
if (pkcs7 == NULL)
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_gnutls_pkcs7_set_crl_raw (pkcs7, &data);
MHD__gnutls_free_datum (&data);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
return 0;
}
/**
* MHD_gnutls_pkcs7_delete_crl - This function deletes a crl from a PKCS7 crl set
* @pkcs7_struct: should contain a MHD_gnutls_pkcs7_t structure
* @indx: the index of the crl to delete
*
* This function will delete a crl from a PKCS7 or RFC2630 crl set.
* Index starts from 0. Returns 0 on success.
*
**/
int
MHD_gnutls_pkcs7_delete_crl (MHD_gnutls_pkcs7_t pkcs7, int indx)
{
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
int result;
char root2[MAX_NAME_SIZE];
if (pkcs7 == NULL)
return GNUTLS_E_INVALID_REQUEST;
/* Step 1. Decode the signed data.
*/
result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
if (result < 0)
{
MHD_gnutls_assert ();
return result;
}
/* Step 2. Delete the crl.
*/
snprintf (root2, sizeof (root2), "crls.?%u", indx + 1);
result = MHD__asn1_write_value (c2, root2, NULL, 0);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto cleanup;
}
/* Step 3. Replace the old content with the new
*/
result =
MHD__gnutls_x509_der_encode_and_copy (c2, "", pkcs7->pkcs7, "content", 0);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
MHD__asn1_delete_structure (&c2);
return 0;
cleanup:
if (c2)
MHD__asn1_delete_structure (&c2);
return result;
}
#endif /* ENABLE_PKI */
-30
View File
@@ -1,30 +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
*
*/
#include "x509.h"
typedef struct MHD_gnutls_pkcs7_int
{
ASN1_TYPE pkcs7;
} MHD_gnutls_pkcs7_int;
-984
View File
@@ -1,984 +0,0 @@
/*
* Copyright (C) 2003, 2004, 2005, 2007 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
*
*/
#include <gnutls_int.h>
#ifdef ENABLE_PKI
#include <gnutls_datum.h>
#include <gnutls_global.h>
#include <gnutls_errors.h>
#include <gnutls_rsa_export.h>
#include <common.h>
#include <gnutls_x509.h>
#include <x509_b64.h>
#include <x509.h>
#include <pkcs12.h>
#include <dn.h>
#include <privkey.h>
#include <extensions.h>
#include <mpi.h>
#include <gnutls_algorithms.h>
#include <gnutls_num.h>
#include "gc.h"
#define PBES2_OID "1.2.840.113549.1.5.13"
#define PBKDF2_OID "1.2.840.113549.1.5.12"
#define DES_EDE3_CBC_OID "1.2.840.113549.3.7"
#define DES_CBC_OID "1.3.14.3.2.7"
/* oid_pbeWithSHAAnd3_KeyTripleDES_CBC */
#define PKCS12_PBE_3DES_SHA1_OID "1.2.840.113549.1.12.1.3"
#define PKCS12_PBE_ARCFOUR_SHA1_OID "1.2.840.113549.1.12.1.1"
#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;
};
struct pbe_enc_params
{
enum MHD_GNUTLS_CipherAlgorithm cipher;
opaque iv[8];
int iv_size;
};
static int read_pbkdf2_params (ASN1_TYPE pbes2_asn,
const MHD_gnutls_datum_t * der,
struct pbkdf2_params *params);
static int read_pbe_enc_params (ASN1_TYPE pbes2_asn,
const MHD_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,
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 readMHD_pkcs12_kdf_params (ASN1_TYPE pbes2_asn,
struct pbkdf2_params *params);
#define PEM_PKCS8 "ENCRYPTED PRIVATE KEY"
#define PEM_UNENCRYPTED_PKCS8 "PRIVATE KEY"
/* Returns a negative error code if the encryption schema in
* the OID is not supported. The schema ID is returned.
*/
static int
check_schema (const char *oid)
{
if (strcmp (oid, PBES2_OID) == 0)
return PBES2;
if (strcmp (oid, PKCS12_PBE_3DES_SHA1_OID) == 0)
return PKCS12_3DES_SHA1;
if (strcmp (oid, PKCS12_PBE_ARCFOUR_SHA1_OID) == 0)
return PKCS12_ARCFOUR_SHA1;
if (strcmp (oid, PKCS12_PBE_RC2_40_SHA1_OID) == 0)
return PKCS12_RC2_40_SHA1;
MHD__gnutls_x509_log ("PKCS encryption schema OID '%s' is unsupported.\n",
oid);
return GNUTLS_E_UNKNOWN_CIPHER_TYPE;
}
/* 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;
MHD_gnutls_datum_t tmp;
switch (schema)
{
case PBES2:
/* Now check the key derivation and the encryption
* functions.
*/
if ((result =
MHD__asn1_create_element (MHD__gnutls_get_pkix (),
"PKIX1.pkcs-5-PBES2-params",
&pbes2_asn)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
/* Decode the parameters.
*/
result = MHD__asn1_der_decoding (&pbes2_asn, data, data_size, NULL);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
tmp.data = (opaque *) data;
tmp.size = data_size;
result = read_pbkdf2_params (pbes2_asn, &tmp, kdf_params);
if (result < 0)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
result = read_pbe_enc_params (pbes2_asn, &tmp, enc_params);
if (result < 0)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
MHD__asn1_delete_structure (&pbes2_asn);
return 0;
break;
case PKCS12_3DES_SHA1:
case PKCS12_ARCFOUR_SHA1:
case PKCS12_RC2_40_SHA1:
if ((schema) == PKCS12_3DES_SHA1)
{
enc_params->cipher = MHD_GNUTLS_CIPHER_3DES_CBC;
enc_params->iv_size = 8;
}
else if ((schema) == PKCS12_ARCFOUR_SHA1)
{
enc_params->cipher = MHD_GNUTLS_CIPHER_ARCFOUR_128;
enc_params->iv_size = 0;
}
else if ((schema) == PKCS12_RC2_40_SHA1)
{
enc_params->cipher = MHD_GNUTLS_CIPHER_RC2_40_CBC;
enc_params->iv_size = 8;
}
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;
}
/* Decode the parameters.
*/
result = MHD__asn1_der_decoding (&pbes2_asn, data, data_size, NULL);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
result = readMHD_pkcs12_kdf_params (pbes2_asn, kdf_params);
if (result < 0)
{
MHD_gnutls_assert ();
goto error;
}
if (enc_params->iv_size)
{
result =
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 (result < 0)
{
MHD_gnutls_assert ();
goto error;
}
}
MHD__asn1_delete_structure (&pbes2_asn);
return 0;
break;
} /* switch */
return GNUTLS_E_UNKNOWN_CIPHER_TYPE;
error:
MHD__asn1_delete_structure (&pbes2_asn);
return result;
}
/* Converts a PKCS #8 key to
* an internal structure (MHD_gnutls_private_key)
* (normally a PKCS #1 encoded RSA key)
*/
static int
decode_pkcs8_key (const MHD_gnutls_datum_t * raw_key,
const char *password, MHD_gnutls_x509_privkey_t pkey)
{
int result, len;
char enc_oid[64];
MHD_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 =
MHD__asn1_create_element (MHD__gnutls_get_pkix (),
"PKIX1.pkcs-8-EncryptedPrivateKeyInfo",
&pkcs8_asn)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
result =
MHD__asn1_der_decoding (&pkcs8_asn, raw_key->data, raw_key->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 (pkcs8_asn, "encryptionAlgorithm.algorithm",
enc_oid, &len);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
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 (pkcs8_asn, raw_key->data,
raw_key->size,
"encryptionAlgorithm.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,
&raw_key->data[params_start],
params_len, &kdf_params, &enc_params);
/* Parameters have been decoded. Now
* decrypt the EncryptedData.
*/
result =
decrypt_data (schema, pkcs8_asn, "encryptedData", password,
&kdf_params, &enc_params, &tmp);
if (result < 0)
{
MHD_gnutls_assert ();
goto error;
}
MHD__asn1_delete_structure (&pkcs8_asn);
result = decode_private_key_info (&tmp, pkey);
MHD__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;
}
MHD_gnutls_assert ();
goto error;
}
return 0;
error:
MHD__asn1_delete_structure (&pbes2_asn);
MHD__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, MHD_gnutls_x509_privkey_t pkey)
{
int ret;
MHD_gnutls_datum_t tmp;
ret = MHD__gnutls_x509_read_value (pkcs8_asn, "privateKey", &tmp, 0);
if (ret < 0)
{
MHD_gnutls_assert ();
goto error;
}
pkey->key = MHD__gnutls_privkey_decode_pkcs1_rsa_key (&tmp, pkey);
MHD__gnutls_free_datum (&tmp);
if (pkey->key == NULL)
{
MHD_gnutls_assert ();
goto error;
}
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)
{
int result, len;
opaque oid[64];
ASN1_TYPE pkcs8_asn = ASN1_TYPE_EMPTY;
if ((result =
MHD__asn1_create_element (MHD__gnutls_get_pkix (),
"PKIX1.pkcs-8-PrivateKeyInfo",
&pkcs8_asn)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
result = MHD__asn1_der_decoding (&pkcs8_asn, der->data, der->size, NULL);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
/* Check the private key algorithm OID
*/
len = sizeof (oid);
result =
MHD__asn1_read_value (pkcs8_asn, "privateKeyAlgorithm.algorithm", oid,
&len);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
/* we only support RSA and DSA private keys.
*/
if (strcmp ((const char *) oid, PK_PKIX1_RSA_OID) == 0)
pkey->pk_algorithm = MHD_GNUTLS_PK_RSA;
else
{
MHD_gnutls_assert ();
MHD__gnutls_x509_log
("PKCS #8 private key OID '%s' is unsupported.\n", oid);
result = GNUTLS_E_UNKNOWN_PK_ALGORITHM;
goto error;
}
/* Get the DER encoding of the actual private key.
*/
if (pkey->pk_algorithm == MHD_GNUTLS_PK_RSA)
result = _decode_pkcs8_rsa_key (pkcs8_asn, pkey);
if (result < 0)
{
MHD_gnutls_assert ();
return result;
}
result = 0;
error:
MHD__asn1_delete_structure (&pkcs8_asn);
return result;
}
/**
* MHD_gnutls_x509_privkey_import_pkcs8 - This function will import a DER or PEM PKCS8 encoded key
* @key: The structure to store the parsed key
* @data: The DER or PEM encoded key.
* @format: One of DER or PEM
* @password: the password to decrypt the key (if it is encrypted).
* @flags: 0 if encrypted or GNUTLS_PKCS_PLAIN if not encrypted.
*
* This function will convert the given DER or PEM encoded PKCS8 2.0 encrypted key
* to the native MHD_gnutls_x509_privkey_t format. The output will be stored in @key.
* Both RSA and DSA keys can be imported, and flags can only be used to indicate
* an unencrypted key.
*
* The @password can be either ASCII or UTF-8 in the default PBES2
* encryption schemas, or ASCII for the PKCS12 schemas.
*
* If the Certificate is PEM encoded it should have a header of "ENCRYPTED PRIVATE KEY",
* or "PRIVATE KEY". You only need to specify the flags if the key is DER encoded, since
* in that case the encryption status cannot be auto-detected.
*
* Returns 0 on success.
*
**/
int
MHD_gnutls_x509_privkey_import_pkcs8 (MHD_gnutls_x509_privkey_t key,
const MHD_gnutls_datum_t * data,
MHD_gnutls_x509_crt_fmt_t format,
const char *password,
unsigned int flags)
{
int result = 0, need_free = 0;
MHD_gnutls_datum_t _data;
if (key == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
_data.data = data->data;
_data.size = data->size;
key->pk_algorithm = MHD_GNUTLS_PK_UNKNOWN;
/* If the Certificate is in PEM format then decode it
*/
if (format == GNUTLS_X509_FMT_PEM)
{
opaque *out;
/* Try the first header
*/
result =
MHD__gnutls_fbase64_decode (PEM_UNENCRYPTED_PKCS8,
data->data, data->size, &out);
if (result < 0)
{ /* Try the encrypted header
*/
result =
MHD__gnutls_fbase64_decode (PEM_PKCS8, data->data, data->size,
&out);
if (result <= 0)
{
if (result == 0)
result = GNUTLS_E_INTERNAL_ERROR;
MHD_gnutls_assert ();
return result;
}
}
else if (flags == 0)
flags |= GNUTLS_PKCS_PLAIN;
_data.data = out;
_data.size = result;
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 (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
if (need_free)
MHD__gnutls_free_datum (&_data);
/* The key has now been decoded.
*/
return 0;
cleanup:
key->pk_algorithm = MHD_GNUTLS_PK_UNKNOWN;
if (need_free)
MHD__gnutls_free_datum (&_data);
return result;
}
/* Reads the PBKDF2 parameters.
*/
static int
read_pbkdf2_params (ASN1_TYPE pbes2_asn,
const MHD_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));
/* Check the key derivation algorithm
*/
len = sizeof (oid);
result =
MHD__asn1_read_value (pbes2_asn, "keyDerivationFunc.algorithm", oid,
&len);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
MHD__gnutls_hard_log ("keyDerivationFunc.algorithm: %s\n", oid);
if (strcmp (oid, PBKDF2_OID) != 0)
{
MHD_gnutls_assert ();
MHD__gnutls_x509_log
("PKCS #8 key derivation OID '%s' is unsupported.\n", oid);
return MHD_gtls_asn2err (result);
}
result =
MHD__asn1_der_decoding_startEnd (pbes2_asn, der->data, der->size,
"keyDerivationFunc.parameters",
&params_start, &params_end);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
params_len = params_end - params_start + 1;
/* Now check 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_der_decoding (&pbkdf2_asn, &der->data[params_start],
params_len, NULL);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
/* read the salt */
params->salt_size = sizeof (params->salt);
result =
MHD__asn1_read_value (pbkdf2_asn, "salt.specified", params->salt,
&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", params->salt_size);
/* read the iteration count
*/
result =
MHD__gnutls_x509_read_uint (pbkdf2_asn, "iterationCount",
&params->iter_count);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
goto error;
}
MHD__gnutls_hard_log ("iterationCount: %d\n", params->iter_count);
/* read the keylength, if it is set.
*/
result =
MHD__gnutls_x509_read_uint (pbkdf2_asn, "keyLength", &params->key_size);
if (result < 0)
{
params->key_size = 0;
}
MHD__gnutls_hard_log ("keyLength: %d\n", params->key_size);
/* We don't read the PRF. We only use the default.
*/
return 0;
error:
MHD__asn1_delete_structure (&pbkdf2_asn);
return result;
}
/* Reads the PBE parameters from PKCS-12 schemas (*&#%*&#% RSA).
*/
static int
readMHD_pkcs12_kdf_params (ASN1_TYPE pbes2_asn, struct pbkdf2_params *params)
{
int result;
memset (params, 0, sizeof (params));
/* read the salt */
params->salt_size = sizeof (params->salt);
result =
MHD__asn1_read_value (pbes2_asn, "salt", params->salt,
&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", params->salt_size);
/* read the iteration count
*/
result =
MHD__gnutls_x509_read_uint (pbes2_asn, "iterations", &params->iter_count);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
goto error;
}
MHD__gnutls_hard_log ("iterationCount: %d\n", params->iter_count);
params->key_size = 0;
return 0;
error:
return result;
}
/* Converts an OID to a gnutls cipher type.
*/
static int
oid2cipher (const char *oid, enum MHD_GNUTLS_CipherAlgorithm *algo)
{
*algo = 0;
if (strcmp (oid, DES_EDE3_CBC_OID) == 0)
{
*algo = MHD_GNUTLS_CIPHER_3DES_CBC;
return 0;
}
if (strcmp (oid, DES_CBC_OID) == 0)
{
*algo = MHD_GNUTLS_CIPHER_DES_CBC;
return 0;
}
MHD__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 MHD_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));
/* Check the encryption algorithm
*/
len = sizeof (oid);
result =
MHD__asn1_read_value (pbes2_asn, "encryptionScheme.algorithm", oid, &len);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
goto error;
}
MHD__gnutls_hard_log ("encryptionScheme.algorithm: %s\n", oid);
if ((result = oid2cipher (oid, &params->cipher)) < 0)
{
MHD_gnutls_assert ();
goto error;
}
result =
MHD__asn1_der_decoding_startEnd (pbes2_asn, der->data, der->size,
"encryptionScheme.parameters",
&params_start, &params_end);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
params_len = params_end - params_start + 1;
/* 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);
}
result =
MHD__asn1_der_decoding (&pbe_asn, &der->data[params_start], params_len,
NULL);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
/* read the IV */
params->iv_size = sizeof (params->iv);
result = MHD__asn1_read_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);
return 0;
error:
MHD__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,
MHD_gnutls_datum_t * decrypted_data)
{
int result;
int data_size;
opaque *data = NULL, *key = NULL;
MHD_gnutls_datum_t dkey, d_iv;
cipher_hd_t ch = NULL;
int key_size;
data_size = 0;
result = MHD__asn1_read_value (pkcs8_asn, root, NULL, &data_size);
if (result != ASN1_MEM_ERROR)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
data = MHD_gnutls_malloc (data_size);
if (data == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_MEMORY_ERROR;
}
result = MHD__asn1_read_value (pkcs8_asn, root, data, &data_size);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
result = MHD_gtls_asn2err (result);
goto error;
}
if (kdf_params->key_size == 0)
{
key_size = MHD__gnutls_cipher_get_key_size (enc_params->cipher);
}
else
key_size = kdf_params->key_size;
key = MHD_gnutls_alloca (key_size);
if (key == NULL)
{
MHD_gnutls_assert ();
result = GNUTLS_E_MEMORY_ERROR;
goto error;
}
/* generate the key
*/
if (schema == PBES2)
{
result = MHD_gc_pbkdf2_sha1 (password, strlen (password),
(const char *) kdf_params->salt,
kdf_params->salt_size,
kdf_params->iter_count, (char *) key,
key_size);
if (result != GC_OK)
{
MHD_gnutls_assert ();
result = GNUTLS_E_DECRYPTION_FAILED;
goto error;
}
}
else
{
result =
MHD_pkcs12_string_to_key (1 /*KEY*/, kdf_params->salt,
kdf_params->salt_size,
kdf_params->iter_count, password,
key_size, key);
if (result < 0)
{
MHD_gnutls_assert ();
goto error;
}
}
/* 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 = MHD_gtls_cipher_init (enc_params->cipher, &dkey, &d_iv);
MHD_gnutls_afree (key);
key = NULL;
if (ch == NULL)
{
MHD_gnutls_assert ();
result = GNUTLS_E_DECRYPTION_FAILED;
goto error;
}
result = MHD_gtls_cipher_decrypt (ch, data, data_size);
if (result < 0)
{
MHD_gnutls_assert ();
goto error;
}
decrypted_data->data = data;
if (MHD_gtls_cipher_get_block_size (enc_params->cipher) != 1)
decrypted_data->size = data_size - data[data_size - 1];
else
decrypted_data->size = data_size;
MHD_gnutls_cipher_deinit (ch);
return 0;
error:
MHD_gnutls_free (data);
MHD_gnutls_afree (key);
if (ch != NULL)
MHD_gnutls_cipher_deinit (ch);
return result;
}
#endif
-264
View File
@@ -1,264 +0,0 @@
/*
* Copyright (C) 2003, 2004, 2005, 2006, 2007 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
*
*/
/* All functions which relate to X.509 certificate signing stuff are
* included here
*/
#include <gnutls_int.h>
#ifdef ENABLE_PKI
#include <gnutls_errors.h>
#include <gnutls_cert.h>
#include <libtasn1.h>
#include <gnutls_global.h>
#include <gnutls_num.h> /* MAX */
#include <gnutls_sig.h>
#include <gnutls_str.h>
#include <gnutls_datum.h>
#include <dn.h>
#include <x509.h>
#include <mpi.h>
#include <sign.h>
#include <common.h>
#include <verify.h>
/* Writes the digest information and the digest in a DER encoded
* structure. The digest info is allocated and stored into the info structure.
*/
static int
encode_ber_digest_info (enum MHD_GNUTLS_HashAlgorithm hash,
const MHD_gnutls_datum_t * digest,
MHD_gnutls_datum_t * info)
{
ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
int result;
const char *algo;
algo = MHD_gtls_x509_mac_to_oid ((enum MHD_GNUTLS_HashAlgorithm) hash);
if (algo == NULL)
{
MHD_gnutls_assert ();
MHD__gnutls_x509_log ("Hash algorithm: %d\n", hash);
return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
}
if ((result = MHD__asn1_create_element (MHD__gnutls_getMHD__gnutls_asn (),
"GNUTLS.DigestInfo",
&dinfo)) != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
return MHD_gtls_asn2err (result);
}
result =
MHD__asn1_write_value (dinfo, "digestAlgorithm.algorithm", algo, 1);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
MHD__asn1_delete_structure (&dinfo);
return MHD_gtls_asn2err (result);
}
/* Write an ASN.1 NULL in the parameters field. This matches RFC
3279 and RFC 4055, although is arguable incorrect from a historic
perspective (see those documents for more information).
Regardless of what is correct, this appears to be what most
implementations do. */
result = MHD__asn1_write_value (dinfo, "digestAlgorithm.parameters",
"\x05\x00", 2);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
MHD__asn1_delete_structure (&dinfo);
return MHD_gtls_asn2err (result);
}
result =
MHD__asn1_write_value (dinfo, "digest", digest->data, digest->size);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
MHD__asn1_delete_structure (&dinfo);
return MHD_gtls_asn2err (result);
}
info->size = 0;
MHD__asn1_der_coding (dinfo, "", NULL, (int *) &info->size, NULL);
info->data = MHD_gnutls_malloc (info->size);
if (info->data == NULL)
{
MHD_gnutls_assert ();
MHD__asn1_delete_structure (&dinfo);
return GNUTLS_E_MEMORY_ERROR;
}
result =
MHD__asn1_der_coding (dinfo, "", info->data, (int *) &info->size, NULL);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
MHD__asn1_delete_structure (&dinfo);
return MHD_gtls_asn2err (result);
}
MHD__asn1_delete_structure (&dinfo);
return 0;
}
/* if hash==MD5 then we do RSA-MD5
* if hash==SHA then we do RSA-SHA
* params[0] is modulus
* params[1] is public key
*/
static int
pkcs1_rsa_sign (enum MHD_GNUTLS_HashAlgorithm hash,
const MHD_gnutls_datum_t * text, mpi_t * params,
int params_len, MHD_gnutls_datum_t * signature)
{
int ret;
opaque _digest[MAX_HASH_SIZE];
GNUTLS_HASH_HANDLE hd;
MHD_gnutls_datum_t digest, info;
hd = MHD_gtls_hash_init (HASH2MAC (hash));
if (hd == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_HASH_FAILED;
}
MHD_gnutls_hash (hd, text->data, text->size);
MHD_gnutls_hash_deinit (hd, _digest);
digest.data = _digest;
digest.size = MHD_gnutls_hash_get_algo_len (HASH2MAC (hash));
/* Encode the digest as a DigestInfo
*/
if ((ret = encode_ber_digest_info (hash, &digest, &info)) != 0)
{
MHD_gnutls_assert ();
return ret;
}
if ((ret =
MHD_gtls_sign (MHD_GNUTLS_PK_RSA, params, params_len, &info,
signature)) < 0)
{
MHD_gnutls_assert ();
MHD__gnutls_free_datum (&info);
return ret;
}
MHD__gnutls_free_datum (&info);
return 0;
}
/* Signs the given data using the parameters from the signer's
* private key.
*
* returns 0 on success.
*
* 'tbs' is the data to be signed
* 'signature' will hold the signature!
* 'hash' is only used in PKCS1 RSA signing.
*/
static int
MHD__gnutls_x509_sign (const MHD_gnutls_datum_t * tbs,
enum MHD_GNUTLS_HashAlgorithm hash,
MHD_gnutls_x509_privkey_t signer,
MHD_gnutls_datum_t * signature)
{
int ret;
switch (signer->pk_algorithm)
{
case MHD_GNUTLS_PK_RSA:
ret =
pkcs1_rsa_sign (hash, tbs, signer->params, signer->params_size,
signature);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
return 0;
break;
default:
MHD_gnutls_assert ();
return GNUTLS_E_INTERNAL_ERROR;
}
}
/* This is the same as the MHD__gnutls_x509_sign, but this one will decode
* the ASN1_TYPE given, and sign the DER data. Actually used to get the DER
* of the TBS and sign it on the fly.
*/
int
MHD__gnutls_x509_sign_tbs (ASN1_TYPE cert, const char *tbs_name,
enum MHD_GNUTLS_HashAlgorithm hash,
MHD_gnutls_x509_privkey_t signer,
MHD_gnutls_datum_t * signature)
{
int result;
opaque *buf;
int buf_size;
MHD_gnutls_datum_t tbs;
buf_size = 0;
MHD__asn1_der_coding (cert, tbs_name, NULL, &buf_size, NULL);
buf = MHD_gnutls_alloca (buf_size);
if (buf == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_MEMORY_ERROR;
}
result = MHD__asn1_der_coding (cert, tbs_name, buf, &buf_size, NULL);
if (result != ASN1_SUCCESS)
{
MHD_gnutls_assert ();
MHD_gnutls_afree (buf);
return MHD_gtls_asn2err (result);
}
tbs.data = buf;
tbs.size = buf_size;
result = MHD__gnutls_x509_sign (&tbs, hash, signer, signature);
MHD_gnutls_afree (buf);
return result;
}
#endif
-28
View File
@@ -1,28 +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
*
*/
int MHD__gnutls_x509_sign_tbs (ASN1_TYPE cert, const char *tbs_name,
enum MHD_GNUTLS_HashAlgorithm hash,
MHD_gnutls_x509_privkey_t signer,
MHD_gnutls_datum_t * signature);
-110
View File
@@ -1111,113 +1111,3 @@ MHD_gnutls_x509_crt_export (MHD_gnutls_x509_crt_t cert,
output_data, output_data_size);
}
#ifdef ENABLE_PKI
/**
* MHD_gnutls_x509_crt_check_revocation - This function checks if the given certificate is revoked
* @cert: should contain a MHD_gnutls_x509_crt_t structure
* @crl_list: should contain a list of MHD_gnutls_x509_crl_t structures
* @crl_list_length: the length of the crl_list
*
* This function will return check if the given certificate is
* revoked. It is assumed that the CRLs have been verified before.
*
* Returns: 0 if the certificate is NOT revoked, and 1 if it is. A
* negative value is returned on error.
**/
int
MHD_gnutls_x509_crt_check_revocation (MHD_gnutls_x509_crt_t cert,
const MHD_gnutls_x509_crl_t * crl_list,
int crl_list_length)
{
opaque serial[64];
opaque cert_serial[64];
size_t serial_size, cert_serial_size;
int ncerts, ret, i, j;
MHD_gnutls_datum_t dn1, dn2;
if (cert == NULL)
{
MHD_gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
}
for (j = 0; j < crl_list_length; j++)
{ /* do for all the crls */
/* Step 1. check if issuer's DN match
*/
ret = MHD__gnutls_x509_crl_get_raw_issuer_dn (crl_list[j], &dn1);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
ret = MHD_gnutls_x509_crt_get_raw_issuer_dn (cert, &dn2);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
ret = MHD__gnutls_x509_compare_raw_dn (&dn1, &dn2);
MHD__gnutls_free_datum (&dn1);
MHD__gnutls_free_datum (&dn2);
if (ret == 0)
{
/* issuers do not match so don't even
* bother checking.
*/
continue;
}
/* Step 2. Read the certificate's serial number
*/
cert_serial_size = sizeof (cert_serial);
ret =
MHD_gnutls_x509_crt_get_serial (cert, cert_serial, &cert_serial_size);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
/* Step 3. cycle through the CRL serials and compare with
* certificate serial we have.
*/
ncerts = MHD_gnutls_x509_crl_get_crt_count (crl_list[j]);
if (ncerts < 0)
{
MHD_gnutls_assert ();
return ncerts;
}
for (i = 0; i < ncerts; i++)
{
serial_size = sizeof (serial);
ret = MHD_gnutls_x509_crl_get_crt_serial (crl_list[j], i, serial,
&serial_size, NULL);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
if (serial_size == cert_serial_size)
{
if (memcmp (serial, cert_serial, serial_size) == 0)
{
/* serials match */
return 1; /* revoked! */
}
}
}
}
return 0; /* not revoked. */
}
#endif
-1
View File
@@ -35,7 +35,6 @@
#include <dn.h>
#include <mpi.h>
#include <extensions.h>
#include <sign.h>
#include <verify.h>
static int MHD__gnutls_asn1_encode_rsa (ASN1_TYPE * c2, mpi_t * params);
-245
View File
@@ -50,14 +50,6 @@ int MHD__gnutls_x509_verify_signature (const MHD_gnutls_datum_t * signed_data,
const MHD_gnutls_datum_t * signature,
MHD_gnutls_x509_crt_t issuer);
static
int is_crl_issuer (MHD_gnutls_x509_crl_t crl,
MHD_gnutls_x509_crt_t issuer_cert);
static int MHD__gnutls_verify_crl2 (MHD_gnutls_x509_crl_t crl,
const MHD_gnutls_x509_crt_t * trusted_cas,
int tcas_size, unsigned int flags,
unsigned int *output);
/* Checks if the issuer of a certificate is a
* Certificate Authority, or if the certificate is the same
* as the issuer (and therefore it doesn't need to be a CA).
@@ -410,22 +402,6 @@ MHD__gnutls_x509_verify_certificate (const MHD_gnutls_x509_crt_t *
return status;
}
/* Check for revoked certificates in the chain
*/
#ifdef ENABLE_PKI
for (i = 0; i < clist_size; i++)
{
ret = MHD_gnutls_x509_crt_check_revocation (certificate_list[i],
CRLs, crls_size);
if (ret == 1)
{ /* revoked */
status |= GNUTLS_CERT_REVOKED;
status |= GNUTLS_CERT_INVALID;
return status;
}
}
#endif
/* Check if the last certificate in the path is self signed.
* In that case ignore it (a certificate is trusted only if it
* leads to a trusted party by us, not the server's).
@@ -795,224 +771,3 @@ MHD_gnutls_x509_crt_verify (MHD_gnutls_x509_crt_t cert,
return 0;
}
#ifdef ENABLE_PKI
/**
* MHD_gnutls_x509_crl_check_issuer - This function checks if the CRL given has the given issuer
* @crl: is the CRL to be checked
* @issuer: is the certificate of a possible issuer
*
* This function will check if the given CRL was issued by the
* given issuer certificate. It will return true (1) if the given CRL was issued
* by the given issuer, and false (0) if not.
*
* A negative value is returned in case of an error.
*
**/
int
MHD_gnutls_x509_crl_check_issuer (MHD_gnutls_x509_crl_t cert,
MHD_gnutls_x509_crt_t issuer)
{
return is_crl_issuer (cert, issuer);
}
/**
* MHD_gnutls_x509_crl_verify - This function verifies the given crl against a given trusted one
* @crl: is the crl to be verified
* @CA_list: is a certificate list that is considered to be trusted one
* @CA_list_length: holds the number of CA certificates in CA_list
* @flags: Flags that may be used to change the verification algorithm. Use OR of the MHD_gnutls_certificate_verify_flags enumerations.
* @verify: will hold the crl verification output.
*
* This function will try to verify the given crl and return its status.
* See MHD_gnutls_x509_crt_list_verify() for a detailed description of
* return values.
*
* Returns 0 on success and a negative value in case of an error.
*
**/
int
MHD_gnutls_x509_crl_verify (MHD_gnutls_x509_crl_t crl,
const MHD_gnutls_x509_crt_t * CA_list,
int CA_list_length, unsigned int flags,
unsigned int *verify)
{
int ret;
/* Verify crl
*/
ret = MHD__gnutls_verify_crl2 (crl, CA_list, CA_list_length, flags, verify);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
return 0;
}
/* The same as above, but here we've got a CRL.
*/
static int
is_crl_issuer (MHD_gnutls_x509_crl_t crl, MHD_gnutls_x509_crt_t issuer_cert)
{
MHD_gnutls_datum_t dn1 = { NULL, 0 }, dn2 =
{
NULL, 0};
int ret;
ret = MHD__gnutls_x509_crl_get_raw_issuer_dn (crl, &dn1);
if (ret < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
ret = MHD_gnutls_x509_crt_get_raw_dn (issuer_cert, &dn2);
if (ret < 0)
{
MHD_gnutls_assert ();
return ret;
}
ret = MHD__gnutls_x509_compare_raw_dn (&dn1, &dn2);
cleanup:
MHD__gnutls_free_datum (&dn1);
MHD__gnutls_free_datum (&dn2);
return ret;
}
static inline MHD_gnutls_x509_crt_t
find_crl_issuer (MHD_gnutls_x509_crl_t crl,
const MHD_gnutls_x509_crt_t * trusted_cas, int tcas_size)
{
int i;
/* this is serial search.
*/
for (i = 0; i < tcas_size; i++)
{
if (is_crl_issuer (crl, trusted_cas[i]) == 1)
return trusted_cas[i];
}
MHD_gnutls_assert ();
return NULL;
}
/*
* Returns only 0 or 1. If 1 it means that the CRL
* was successfuly verified.
*
* 'flags': an OR of the MHD_gnutls_certificate_verify_flags enumeration.
*
* Output will hold information about the verification
* procedure.
*/
static int
MHD__gnutls_verify_crl2 (MHD_gnutls_x509_crl_t crl,
const MHD_gnutls_x509_crt_t * trusted_cas,
int tcas_size, unsigned int flags,
unsigned int *output)
{
/* CRL is ignored for now */
MHD_gnutls_datum_t crl_signed_data = { NULL, 0 };
MHD_gnutls_datum_t crl_signature = { NULL, 0 };
MHD_gnutls_x509_crt_t issuer;
int ret, result;
if (output)
*output = 0;
if (tcas_size >= 1)
issuer = find_crl_issuer (crl, trusted_cas, tcas_size);
else
{
MHD_gnutls_assert ();
if (output)
*output |= GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID;
return 0;
}
/* issuer is not in trusted certificate
* authorities.
*/
if (issuer == NULL)
{
MHD_gnutls_assert ();
if (output)
*output |= GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_INVALID;
return 0;
}
if (!(flags & GNUTLS_VERIFY_DISABLE_CA_SIGN))
{
if (MHD_gnutls_x509_crt_get_ca_status (issuer, NULL) != 1)
{
MHD_gnutls_assert ();
if (output)
*output |= GNUTLS_CERT_SIGNER_NOT_CA | GNUTLS_CERT_INVALID;
return 0;
}
}
result =
MHD__gnutls_x509_get_signed_data (crl->crl, "tbsCertList",
&crl_signed_data);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
result =
MHD__gnutls_x509_get_signature (crl->crl, "signature", &crl_signature);
if (result < 0)
{
MHD_gnutls_assert ();
goto cleanup;
}
ret =
MHD__gnutls_x509_verify_signature (&crl_signed_data, &crl_signature,
issuer);
if (ret < 0)
{
MHD_gnutls_assert ();
}
else if (ret == 0)
{
MHD_gnutls_assert ();
/* error. ignore it */
if (output)
*output |= GNUTLS_CERT_INVALID;
ret = 0;
}
{
int sigalg;
sigalg = MHD_gnutls_x509_crl_get_signature_algorithm (crl);
if (((sigalg == GNUTLS_SIGN_RSA_MD2) &&
!(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2)) ||
((sigalg == GNUTLS_SIGN_RSA_MD5) &&
!(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5)))
{
if (output)
*output |= GNUTLS_CERT_INSECURE_ALGORITHM | GNUTLS_CERT_INVALID;
}
}
result = ret;
cleanup:
MHD__gnutls_free_datum (&crl_signed_data);
MHD__gnutls_free_datum (&crl_signature);
return result;
}
#endif