mirror of
https://git.gnunet.org/libmicrohttpd.git
synced 2026-10-06 04:03:18 +03:00
dce
This commit is contained in:
1 parent
a61b09be33
commit
e81f372ed1
15 files changed
+1
-3874
No files matched your search
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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", ¶ms[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", ¶ms[1])) < 0)
|
||||
{
|
||||
MHD_gnutls_assert ();
|
||||
MHD__asn1_delete_structure (&spk);
|
||||
MHD_gtls_mpi_release (¶ms[0]);
|
||||
return GNUTLS_E_ASN1_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
/* Read g */
|
||||
|
||||
if ((result = MHD__gnutls_x509_read_int (spk, "g", ¶ms[2])) < 0)
|
||||
{
|
||||
MHD_gnutls_assert ();
|
||||
MHD__asn1_delete_structure (&spk);
|
||||
MHD_gtls_mpi_release (¶ms[0]);
|
||||
MHD_gtls_mpi_release (¶ms[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, ¶ms[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;
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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;
|
||||
@@ -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",
|
||||
¶ms_start, ¶ms_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",
|
||||
¶ms_start, ¶ms_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,
|
||||
¶ms->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",
|
||||
¶ms->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", ¶ms->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,
|
||||
¶ms->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", ¶ms->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, ¶ms->cipher)) < 0)
|
||||
{
|
||||
MHD_gnutls_assert ();
|
||||
goto error;
|
||||
}
|
||||
|
||||
result =
|
||||
MHD__asn1_der_decoding_startEnd (pbes2_asn, der->data, der->size,
|
||||
"encryptionScheme.parameters",
|
||||
¶ms_start, ¶ms_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, ¶ms->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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
Reference in new issue
Block a user