|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* Copyright (C) 2003-2016 Free Software Foundation, Inc.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Authors: Nikos Mavrogiannopoulos, Simon Josefsson, Howard Chu
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This file is part of GnuTLS.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* The GnuTLS is free software; you can redistribute it and/or
|
|
Packit Service |
4684c1 |
* modify it under the terms of the GNU Lesser General Public License
|
|
Packit Service |
4684c1 |
* as published by the Free Software Foundation; either version 2.1 of
|
|
Packit Service |
4684c1 |
* the License, or (at your option) any later version.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This library is distributed in the hope that it will be useful, but
|
|
Packit Service |
4684c1 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
4684c1 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
4684c1 |
* Lesser General Public License for more details.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit Service |
4684c1 |
* along with this program. If not, see <https://www.gnu.org/licenses/>
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include "gnutls_int.h"
|
|
Packit Service |
4684c1 |
#include <datum.h>
|
|
Packit Service |
4684c1 |
#include <global.h>
|
|
Packit Service |
4684c1 |
#include "errors.h"
|
|
Packit Service |
4684c1 |
#include <common.h>
|
|
Packit Service |
4684c1 |
#include <gnutls/x509-ext.h>
|
|
Packit Service |
4684c1 |
#include <x509.h>
|
|
Packit Service |
4684c1 |
#include <x509_b64.h>
|
|
Packit Service |
4684c1 |
#include <x509_int.h>
|
|
Packit Service |
4684c1 |
#include <libtasn1.h>
|
|
Packit Service |
4684c1 |
#include <pk.h>
|
|
Packit Service |
4684c1 |
#include <pkcs11_int.h>
|
|
Packit Service |
4684c1 |
#include "urls.h"
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_x509_tlsfeatures_init:
|
|
Packit Service |
4684c1 |
* @f: The TLS features
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will initialize a X.509 TLS features extension structure
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
|
|
Packit Service |
4684c1 |
* otherwise a negative error value.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.5.1
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int gnutls_x509_tlsfeatures_init(gnutls_x509_tlsfeatures_t *f)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
*f = gnutls_calloc(1, sizeof(struct gnutls_x509_tlsfeatures_st));
|
|
Packit Service |
4684c1 |
if (*f == NULL)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_x509_tlsfeatures_deinit:
|
|
Packit Service |
4684c1 |
* @f: The TLS features
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will deinitialize a X.509 TLS features extension structure
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.5.1
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
void gnutls_x509_tlsfeatures_deinit(gnutls_x509_tlsfeatures_t f)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
gnutls_free(f);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_x509_tlsfeatures_get:
|
|
Packit Service |
4684c1 |
* @f: The TLS features
|
|
Packit Service |
4684c1 |
* @idx: The index of the feature to get
|
|
Packit Service |
4684c1 |
* @feature: If the function succeeds, the feature will be stored in this variable
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will get a feature from the X.509 TLS features
|
|
Packit Service |
4684c1 |
* extension structure.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
|
|
Packit Service |
4684c1 |
* otherwise a negative error value.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.5.1
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int gnutls_x509_tlsfeatures_get(gnutls_x509_tlsfeatures_t f, unsigned idx, unsigned int *feature)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (f == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (idx >= f->size) {
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
*feature = f->feature[idx];
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_x509_crt_get_tlsfeatures:
|
|
Packit Service |
4684c1 |
* @crt: A X.509 certificate
|
|
Packit Service |
4684c1 |
* @features: If the function succeeds, the
|
|
Packit Service |
4684c1 |
* features will be stored in this variable.
|
|
Packit Service |
4684c1 |
* @flags: zero or %GNUTLS_EXT_FLAG_APPEND
|
|
Packit Service |
4684c1 |
* @critical: the extension status
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will get the X.509 TLS features
|
|
Packit Service |
4684c1 |
* extension structure from the certificate. The
|
|
Packit Service |
4684c1 |
* returned structure needs to be freed using
|
|
Packit Service |
4684c1 |
* gnutls_x509_tlsfeatures_deinit().
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* When the @flags is set to %GNUTLS_EXT_FLAG_APPEND,
|
|
Packit Service |
4684c1 |
* then if the @features structure is empty this function will behave
|
|
Packit Service |
4684c1 |
* identically as if the flag was not set. Otherwise if there are elements
|
|
Packit Service |
4684c1 |
* in the @features structure then they will be merged with.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Note that @features must be initialized prior to calling this function.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
|
|
Packit Service |
4684c1 |
* otherwise a negative error value.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.5.1
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int gnutls_x509_crt_get_tlsfeatures(gnutls_x509_crt_t crt,
|
|
Packit Service |
4684c1 |
gnutls_x509_tlsfeatures_t features,
|
|
Packit Service |
4684c1 |
unsigned int flags,
|
|
Packit Service |
4684c1 |
unsigned int *critical)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
gnutls_datum_t der;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (crt == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if ((ret =
|
|
Packit Service |
4684c1 |
_gnutls_x509_crt_get_extension(crt, GNUTLS_X509EXT_OID_TLSFEATURES, 0,
|
|
Packit Service |
4684c1 |
&der, critical)) < 0)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (der.size == 0 || der.data == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_x509_ext_import_tlsfeatures(&der, features, flags);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = 0;
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
gnutls_free(der.data);
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_x509_crt_set_tlsfeatures:
|
|
Packit Service |
4684c1 |
* @crt: A X.509 certificate
|
|
Packit Service |
4684c1 |
* @features: If the function succeeds, the
|
|
Packit Service |
4684c1 |
* features will be added to the certificate.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will set the certificates
|
|
Packit Service |
4684c1 |
* X.509 TLS extension from the given structure.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
|
|
Packit Service |
4684c1 |
* otherwise a negative error value.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.5.1
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int gnutls_x509_crt_set_tlsfeatures(gnutls_x509_crt_t crt,
|
|
Packit Service |
4684c1 |
gnutls_x509_tlsfeatures_t features)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
gnutls_datum_t der;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (crt == NULL || features == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_x509_ext_export_tlsfeatures(features, &der;;
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_x509_crt_set_extension(crt, GNUTLS_X509EXT_OID_TLSFEATURES, &der, 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&der;;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_x509_tls_features_check_crt:
|
|
Packit Service |
4684c1 |
* @feat: a set of TLSFeatures
|
|
Packit Service |
4684c1 |
* @cert: the certificate to be checked
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will check the provided certificate against the TLSFeatures
|
|
Packit Service |
4684c1 |
* set in @feat using the RFC7633 p.4.2.2 rules. It will check whether the certificate
|
|
Packit Service |
4684c1 |
* contains the features in @feat or a superset.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: non-zero if the provided certificate complies, and zero otherwise.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.5.1
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
unsigned gnutls_x509_tlsfeatures_check_crt(gnutls_x509_tlsfeatures_t feat,
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_t cert)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
gnutls_x509_tlsfeatures_t cfeat;
|
|
Packit Service |
4684c1 |
unsigned i, j, uret, found;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (feat->size == 0)
|
|
Packit Service |
4684c1 |
return 1; /* shortcut; no constraints to check */
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_x509_tlsfeatures_init(&cfeat);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_x509_crt_get_tlsfeatures(cert, cfeat, 0, NULL);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
uret = 0;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* if cert's features cannot be a superset */
|
|
Packit Service |
4684c1 |
if (feat->size > cfeat->size) {
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("certificate has %u, while issuer has %u tlsfeatures\n", cfeat->size, feat->size);
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
uret = 0;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i=0;i<feat->size;i++) {
|
|
Packit Service |
4684c1 |
found = 0;
|
|
Packit Service |
4684c1 |
for (j=0;j<cfeat->size;j++) {
|
|
Packit Service |
4684c1 |
if (feat->feature[i] == cfeat->feature[j]) {
|
|
Packit Service |
4684c1 |
found = 1;
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (found == 0) {
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("feature %d was not found in cert\n", (int)feat->feature[i]);
|
|
Packit Service |
4684c1 |
uret = 0;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
uret = 1;
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
gnutls_x509_tlsfeatures_deinit(cfeat);
|
|
Packit Service |
4684c1 |
return uret;
|
|
Packit Service |
4684c1 |
}
|