|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* Copyright (C) 2003-2012 Free Software Foundation, Inc.
|
|
Packit Service |
4684c1 |
* Copyright (C) 2012 Nikos Mavrogiannopoulos
|
|
Packit Service |
4684c1 |
* Copyright (C) 2017 Red Hat, Inc.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Author: Nikos Mavrogiannopoulos
|
|
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 |
/* Functions that relate on PKCS12 packet parsing.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include "gnutls_int.h"
|
|
Packit Service |
4684c1 |
#include <libtasn1.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include <datum.h>
|
|
Packit Service |
4684c1 |
#include <global.h>
|
|
Packit Service |
4684c1 |
#include "errors.h"
|
|
Packit Service |
4684c1 |
#include <num.h>
|
|
Packit Service |
4684c1 |
#include <common.h>
|
|
Packit Service |
4684c1 |
#include <x509_b64.h>
|
|
Packit Service |
4684c1 |
#include "x509_int.h"
|
|
Packit Service |
4684c1 |
#include "pkcs7_int.h"
|
|
Packit Service |
4684c1 |
#include <random.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Decodes the PKCS #12 auth_safe, and returns the allocated raw data,
|
|
Packit Service |
4684c1 |
* which holds them. Returns an ASN1_TYPE of authenticatedSafe.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
_decode_pkcs12_auth_safe(ASN1_TYPE pkcs12, ASN1_TYPE * authen_safe,
|
|
Packit Service |
4684c1 |
gnutls_datum_t * raw)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
char oid[MAX_OID_SIZE];
|
|
Packit Service |
4684c1 |
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
|
|
Packit Service |
4684c1 |
gnutls_datum_t auth_safe = { NULL, 0 };
|
|
Packit Service |
4684c1 |
int len, result;
|
|
Packit Service |
4684c1 |
char error_str[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
len = sizeof(oid) - 1;
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
asn1_read_value(pkcs12, "authSafe.contentType", oid, &len;;
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (strcmp(oid, DATA_OID) != 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("Unknown PKCS12 Content OID '%s'\n",
|
|
Packit Service |
4684c1 |
oid);
|
|
Packit Service |
4684c1 |
return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Step 1. Read the content data
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
_gnutls_x509_read_string(pkcs12, "authSafe.content",
|
|
Packit Service |
4684c1 |
&auth_safe, ASN1_ETYPE_OCTET_STRING, 1);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Step 2. Extract the authenticatedSafe.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if ((result = asn1_create_element
|
|
Packit Service |
4684c1 |
(_gnutls_get_pkix(), "PKIX1.pkcs-12-AuthenticatedSafe",
|
|
Packit Service |
4684c1 |
&c2)) != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
asn1_der_decoding(&c2, auth_safe.data, auth_safe.size,
|
|
Packit Service |
4684c1 |
error_str);
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("DER error: %s\n", error_str);
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (raw == NULL) {
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&auth_safe);
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
raw->data = auth_safe.data;
|
|
Packit Service |
4684c1 |
raw->size = auth_safe.size;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (authen_safe)
|
|
Packit Service |
4684c1 |
*authen_safe = c2;
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
asn1_delete_structure(&c2;;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
if (c2)
|
|
Packit Service |
4684c1 |
asn1_delete_structure(&c2;;
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&auth_safe);
|
|
Packit Service |
4684c1 |
return result;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int pkcs12_reinit(gnutls_pkcs12_t pkcs12)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int result;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (pkcs12->pkcs12)
|
|
Packit Service |
4684c1 |
asn1_delete_structure(&pkcs12->pkcs12);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result = asn1_create_element(_gnutls_get_pkix(),
|
|
Packit Service |
4684c1 |
"PKIX1.pkcs-12-PFX",
|
|
Packit Service |
4684c1 |
&pkcs12->pkcs12);
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs12_init:
|
|
Packit Service |
4684c1 |
* @pkcs12: A pointer to the type to be initialized
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will initialize a PKCS12 type. PKCS12 structures
|
|
Packit Service |
4684c1 |
* usually contain lists of X.509 Certificates and X.509 Certificate
|
|
Packit Service |
4684c1 |
* revocation lists.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int gnutls_pkcs12_init(gnutls_pkcs12_t * pkcs12)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
*pkcs12 = gnutls_calloc(1, sizeof(gnutls_pkcs12_int));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (*pkcs12) {
|
|
Packit Service |
4684c1 |
int result = pkcs12_reinit(*pkcs12);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
gnutls_free(*pkcs12);
|
|
Packit Service |
4684c1 |
return result;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
return 0; /* success */
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs12_deinit:
|
|
Packit Service |
4684c1 |
* @pkcs12: The type to be initialized
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will deinitialize a PKCS12 type.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
void gnutls_pkcs12_deinit(gnutls_pkcs12_t pkcs12)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (!pkcs12)
|
|
Packit Service |
4684c1 |
return;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (pkcs12->pkcs12)
|
|
Packit Service |
4684c1 |
asn1_delete_structure(&pkcs12->pkcs12);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_free(pkcs12);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs12_import:
|
|
Packit Service |
4684c1 |
* @pkcs12: The data to store the parsed PKCS12.
|
|
Packit Service |
4684c1 |
* @data: The DER or PEM encoded PKCS12.
|
|
Packit Service |
4684c1 |
* @format: One of DER or PEM
|
|
Packit Service |
4684c1 |
* @flags: an ORed sequence of gnutls_privkey_pkcs8_flags
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will convert the given DER or PEM encoded PKCS12
|
|
Packit Service |
4684c1 |
* to the native gnutls_pkcs12_t format. The output will be stored in 'pkcs12'.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* If the PKCS12 is PEM encoded it should have a header of "PKCS12".
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
gnutls_pkcs12_import(gnutls_pkcs12_t pkcs12,
|
|
Packit Service |
4684c1 |
const gnutls_datum_t * data,
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_fmt_t format, unsigned int flags)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int result = 0, need_free = 0;
|
|
Packit Service |
4684c1 |
gnutls_datum_t _data;
|
|
Packit Service |
4684c1 |
char error_str[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_data.data = data->data;
|
|
Packit Service |
4684c1 |
_data.size = data->size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (pkcs12 == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* If the PKCS12 is in PEM format then decode it
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
if (format == GNUTLS_X509_FMT_PEM) {
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
_gnutls_fbase64_decode(PEM_PKCS12, data->data,
|
|
Packit Service |
4684c1 |
data->size, &_data);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return result;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
need_free = 1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (pkcs12->expanded) {
|
|
Packit Service |
4684c1 |
result = pkcs12_reinit(pkcs12);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
pkcs12->expanded = 1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
asn1_der_decoding(&pkcs12->pkcs12, _data.data, _data.size,
|
|
Packit Service |
4684c1 |
error_str);
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("DER error: %s\n", error_str);
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (need_free)
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&_data);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
if (need_free)
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&_data);
|
|
Packit Service |
4684c1 |
return result;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs12_export:
|
|
Packit Service |
4684c1 |
* @pkcs12: A pkcs12 type
|
|
Packit Service |
4684c1 |
* @format: the format of output params. One of PEM or DER.
|
|
Packit Service |
4684c1 |
* @output_data: will contain a structure PEM or DER encoded
|
|
Packit Service |
4684c1 |
* @output_data_size: holds the size of output_data (and will be
|
|
Packit Service |
4684c1 |
* replaced by the actual size of parameters)
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will export the pkcs12 structure to DER or PEM format.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* If the buffer provided is not long enough to hold the output, then
|
|
Packit Service |
4684c1 |
* *output_data_size will be updated and GNUTLS_E_SHORT_MEMORY_BUFFER
|
|
Packit Service |
4684c1 |
* will be returned.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* If the structure is PEM encoded, it will have a header
|
|
Packit Service |
4684c1 |
* of "BEGIN PKCS12".
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: In case of failure a negative error code will be
|
|
Packit Service |
4684c1 |
* returned, and 0 on success.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
gnutls_pkcs12_export(gnutls_pkcs12_t pkcs12,
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_fmt_t format, void *output_data,
|
|
Packit Service |
4684c1 |
size_t * output_data_size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (pkcs12 == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return _gnutls_x509_export_int(pkcs12->pkcs12, format, PEM_PKCS12,
|
|
Packit Service |
4684c1 |
output_data, output_data_size);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs12_export2:
|
|
Packit Service |
4684c1 |
* @pkcs12: A pkcs12 type
|
|
Packit Service |
4684c1 |
* @format: the format of output params. One of PEM or DER.
|
|
Packit Service |
4684c1 |
* @out: will contain a structure PEM or DER encoded
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will export the pkcs12 structure to DER or PEM format.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* The output buffer is allocated using gnutls_malloc().
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* If the structure is PEM encoded, it will have a header
|
|
Packit Service |
4684c1 |
* of "BEGIN PKCS12".
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: In case of failure a negative error code will be
|
|
Packit Service |
4684c1 |
* returned, and 0 on success.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.1.3
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
gnutls_pkcs12_export2(gnutls_pkcs12_t pkcs12,
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_fmt_t format, gnutls_datum_t * out)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (pkcs12 == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return _gnutls_x509_export_int2(pkcs12->pkcs12, format, PEM_PKCS12,
|
|
Packit Service |
4684c1 |
out);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int oid2bag(const char *oid)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (strcmp(oid, BAG_PKCS8_KEY) == 0)
|
|
Packit Service |
4684c1 |
return GNUTLS_BAG_PKCS8_KEY;
|
|
Packit Service |
4684c1 |
if (strcmp(oid, BAG_PKCS8_ENCRYPTED_KEY) == 0)
|
|
Packit Service |
4684c1 |
return GNUTLS_BAG_PKCS8_ENCRYPTED_KEY;
|
|
Packit Service |
4684c1 |
if (strcmp(oid, BAG_CERTIFICATE) == 0)
|
|
Packit Service |
4684c1 |
return GNUTLS_BAG_CERTIFICATE;
|
|
Packit Service |
4684c1 |
if (strcmp(oid, BAG_CRL) == 0)
|
|
Packit Service |
4684c1 |
return GNUTLS_BAG_CRL;
|
|
Packit Service |
4684c1 |
if (strcmp(oid, BAG_SECRET) == 0)
|
|
Packit Service |
4684c1 |
return GNUTLS_BAG_SECRET;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return GNUTLS_BAG_UNKNOWN;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static const char *bag_to_oid(int bag)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
switch (bag) {
|
|
Packit Service |
4684c1 |
case GNUTLS_BAG_PKCS8_KEY:
|
|
Packit Service |
4684c1 |
return BAG_PKCS8_KEY;
|
|
Packit Service |
4684c1 |
case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
|
|
Packit Service |
4684c1 |
return BAG_PKCS8_ENCRYPTED_KEY;
|
|
Packit Service |
4684c1 |
case GNUTLS_BAG_CERTIFICATE:
|
|
Packit Service |
4684c1 |
return BAG_CERTIFICATE;
|
|
Packit Service |
4684c1 |
case GNUTLS_BAG_CRL:
|
|
Packit Service |
4684c1 |
return BAG_CRL;
|
|
Packit Service |
4684c1 |
case GNUTLS_BAG_SECRET:
|
|
Packit Service |
4684c1 |
return BAG_SECRET;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
return NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Decodes the SafeContents, and puts the output in
|
|
Packit Service |
4684c1 |
* the given bag.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
_pkcs12_decode_safe_contents(const gnutls_datum_t * content,
|
|
Packit Service |
4684c1 |
gnutls_pkcs12_bag_t bag)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
char oid[MAX_OID_SIZE], root[MAX_NAME_SIZE];
|
|
Packit Service |
4684c1 |
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
|
|
Packit Service |
4684c1 |
int len, result;
|
|
Packit Service |
4684c1 |
int bag_type;
|
|
Packit Service |
4684c1 |
gnutls_datum_t attr_val;
|
|
Packit Service |
4684c1 |
gnutls_datum_t t;
|
|
Packit Service |
4684c1 |
int count = 0, attributes, j;
|
|
Packit Service |
4684c1 |
unsigned i;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Step 1. Extract the SEQUENCE.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if ((result = asn1_create_element
|
|
Packit Service |
4684c1 |
(_gnutls_get_pkix(), "PKIX1.pkcs-12-SafeContents",
|
|
Packit Service |
4684c1 |
&c2)) != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
asn1_der_decoding(&c2, content->data, content->size, NULL);
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Count the number of bags
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result = asn1_number_of_elements(c2, "", &count);
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
bag->bag_elements = MIN(MAX_BAG_ELEMENTS, count);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i = 0; i < bag->bag_elements; i++) {
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
snprintf(root, sizeof(root), "?%u.bagId", i + 1);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
len = sizeof(oid);
|
|
Packit Service |
4684c1 |
result = asn1_read_value(c2, root, oid, &len;;
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Read the Bag type
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
bag_type = oid2bag(oid);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (bag_type < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Read the Bag Value
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
snprintf(root, sizeof(root), "?%u.bagValue", i + 1);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
_gnutls_x509_read_value(c2, root,
|
|
Packit Service |
4684c1 |
&bag->element[i].data);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (bag_type == GNUTLS_BAG_CERTIFICATE
|
|
Packit Service |
4684c1 |
|| bag_type == GNUTLS_BAG_CRL
|
|
Packit Service |
4684c1 |
|| bag_type == GNUTLS_BAG_SECRET) {
|
|
Packit Service |
4684c1 |
gnutls_datum_t tmp = bag->element[i].data;
|
|
Packit Service |
4684c1 |
bag->element[i].data.data = NULL;
|
|
Packit Service |
4684c1 |
bag->element[i].data.size = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
_pkcs12_decode_crt_bag(bag_type, &tmp,
|
|
Packit Service |
4684c1 |
&bag->element[i].data);
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&tmp);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* read the bag attributes
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
snprintf(root, sizeof(root), "?%u.bagAttributes", i + 1);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result = asn1_number_of_elements(c2, root, &attributes);
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS
|
|
Packit Service |
4684c1 |
&& result != ASN1_ELEMENT_NOT_FOUND) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (attributes < 0)
|
|
Packit Service |
4684c1 |
attributes = 1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (result != ASN1_ELEMENT_NOT_FOUND)
|
|
Packit Service |
4684c1 |
for (j = 0; j < attributes; j++) {
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
snprintf(root, sizeof(root),
|
|
Packit Service |
4684c1 |
"?%u.bagAttributes.?%u", i + 1,
|
|
Packit Service |
4684c1 |
j + 1);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
_gnutls_x509_decode_and_read_attribute
|
|
Packit Service |
4684c1 |
(c2, root, oid, sizeof(oid), &attr_val,
|
|
Packit Service |
4684c1 |
1, 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
continue; /* continue in case we find some known attributes */
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (strcmp(oid, KEY_ID_OID) == 0) {
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
_gnutls_x509_decode_string
|
|
Packit Service |
4684c1 |
(ASN1_ETYPE_OCTET_STRING,
|
|
Packit Service |
4684c1 |
attr_val.data, attr_val.size,
|
|
Packit Service |
4684c1 |
&t, 1);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&attr_val);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
_gnutls_debug_log
|
|
Packit Service |
4684c1 |
("Error decoding PKCS12 Bag Attribute OID '%s'\n",
|
|
Packit Service |
4684c1 |
oid);
|
|
Packit Service |
4684c1 |
continue;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&bag->element[i].local_key_id);
|
|
Packit Service |
4684c1 |
bag->element[i].local_key_id.data = t.data;
|
|
Packit Service |
4684c1 |
bag->element[i].local_key_id.size = t.size;
|
|
Packit Service |
4684c1 |
} else if (strcmp(oid, FRIENDLY_NAME_OID) == 0 && bag->element[i].friendly_name == NULL) {
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
_gnutls_x509_decode_string
|
|
Packit Service |
4684c1 |
(ASN1_ETYPE_BMP_STRING,
|
|
Packit Service |
4684c1 |
attr_val.data, attr_val.size,
|
|
Packit Service |
4684c1 |
&t, 1);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&attr_val);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
_gnutls_debug_log
|
|
Packit Service |
4684c1 |
("Error decoding PKCS12 Bag Attribute OID '%s'\n",
|
|
Packit Service |
4684c1 |
oid);
|
|
Packit Service |
4684c1 |
continue;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_free(bag->element[i].friendly_name);
|
|
Packit Service |
4684c1 |
bag->element[i].friendly_name = (char *) t.data;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&attr_val);
|
|
Packit Service |
4684c1 |
_gnutls_debug_log
|
|
Packit Service |
4684c1 |
("Unknown PKCS12 Bag Attribute OID '%s'\n",
|
|
Packit Service |
4684c1 |
oid);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
bag->element[i].type = bag_type;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
if (c2)
|
|
Packit Service |
4684c1 |
asn1_delete_structure(&c2;;
|
|
Packit Service |
4684c1 |
return result;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
_parse_safe_contents(ASN1_TYPE sc, const char *sc_name,
|
|
Packit Service |
4684c1 |
gnutls_pkcs12_bag_t bag)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
gnutls_datum_t content = { NULL, 0 };
|
|
Packit Service |
4684c1 |
int result;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Step 1. Extract the content.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
_gnutls_x509_read_string(sc, sc_name, &content,
|
|
Packit Service |
4684c1 |
ASN1_ETYPE_OCTET_STRING, 1);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result = _pkcs12_decode_safe_contents(&content, bag);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&content);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&content);
|
|
Packit Service |
4684c1 |
return result;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs12_get_bag:
|
|
Packit Service |
4684c1 |
* @pkcs12: A pkcs12 type
|
|
Packit Service |
4684c1 |
* @indx: contains the index of the bag to extract
|
|
Packit Service |
4684c1 |
* @bag: An initialized bag, where the contents of the bag will be copied
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will return a Bag from the PKCS12 structure.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* After the last Bag has been read
|
|
Packit Service |
4684c1 |
* %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
gnutls_pkcs12_get_bag(gnutls_pkcs12_t pkcs12,
|
|
Packit Service |
4684c1 |
int indx, gnutls_pkcs12_bag_t bag)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
|
|
Packit Service |
4684c1 |
int result, len;
|
|
Packit Service |
4684c1 |
char root2[MAX_NAME_SIZE];
|
|
Packit Service |
4684c1 |
char oid[MAX_OID_SIZE];
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (pkcs12 == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Step 1. decode the data.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result = _decode_pkcs12_auth_safe(pkcs12->pkcs12, &c2, NULL);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return result;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Step 2. Parse the AuthenticatedSafe
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
snprintf(root2, sizeof(root2), "?%u.contentType", indx + 1);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
len = sizeof(oid) - 1;
|
|
Packit Service |
4684c1 |
result = asn1_read_value(c2, root2, oid, &len;;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (result == ASN1_ELEMENT_NOT_FOUND) {
|
|
Packit Service |
4684c1 |
result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Not encrypted Bag
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
snprintf(root2, sizeof(root2), "?%u.content", indx + 1);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (strcmp(oid, DATA_OID) == 0) {
|
|
Packit Service |
4684c1 |
result = _parse_safe_contents(c2, root2, bag);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* ENC_DATA_OID needs decryption */
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result = _gnutls_x509_read_value(c2, root2, &bag->element[0].data);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
bag->element[0].type = GNUTLS_BAG_ENCRYPTED;
|
|
Packit Service |
4684c1 |
bag->bag_elements = 1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
if (c2)
|
|
Packit Service |
4684c1 |
asn1_delete_structure(&c2;;
|
|
Packit Service |
4684c1 |
return result;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Creates an empty PFX structure for the PKCS12 structure.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
static int create_empty_pfx(ASN1_TYPE pkcs12)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
uint8_t three = 3;
|
|
Packit Service |
4684c1 |
int result;
|
|
Packit Service |
4684c1 |
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Use version 3
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result = asn1_write_value(pkcs12, "version", &three, 1);
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Write the content type of the data
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
asn1_write_value(pkcs12, "authSafe.contentType", DATA_OID, 1);
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Check if the authenticatedSafe content is empty, and encode a
|
|
Packit Service |
4684c1 |
* null one in that case.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if ((result = asn1_create_element
|
|
Packit Service |
4684c1 |
(_gnutls_get_pkix(), "PKIX1.pkcs-12-AuthenticatedSafe",
|
|
Packit Service |
4684c1 |
&c2)) != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
_gnutls_x509_der_encode_and_copy(c2, "", pkcs12,
|
|
Packit Service |
4684c1 |
"authSafe.content", 1);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
asn1_delete_structure(&c2;;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
asn1_delete_structure(&c2;;
|
|
Packit Service |
4684c1 |
return result;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs12_set_bag:
|
|
Packit Service |
4684c1 |
* @pkcs12: should contain a gnutls_pkcs12_t type
|
|
Packit Service |
4684c1 |
* @bag: An initialized bag
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will insert a Bag into the PKCS12 structure.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int gnutls_pkcs12_set_bag(gnutls_pkcs12_t pkcs12, gnutls_pkcs12_bag_t bag)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
|
|
Packit Service |
4684c1 |
ASN1_TYPE safe_cont = ASN1_TYPE_EMPTY;
|
|
Packit Service |
4684c1 |
int result;
|
|
Packit Service |
4684c1 |
int enc = 0, dum = 1;
|
|
Packit Service |
4684c1 |
char null;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (pkcs12 == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Step 1. Check if the pkcs12 structure is empty. In that
|
|
Packit Service |
4684c1 |
* case generate an empty PFX.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
asn1_read_value(pkcs12->pkcs12, "authSafe.content", &null,
|
|
Packit Service |
4684c1 |
&dum;;
|
|
Packit Service |
4684c1 |
if (result == ASN1_VALUE_NOT_FOUND) {
|
|
Packit Service |
4684c1 |
result = create_empty_pfx(pkcs12->pkcs12);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return result;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Step 2. decode the authenticatedSafe.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result = _decode_pkcs12_auth_safe(pkcs12->pkcs12, &c2, NULL);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return result;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Step 3. Encode the bag elements into a SafeContents
|
|
Packit Service |
4684c1 |
* structure.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result = _pkcs12_encode_safe_contents(bag, &safe_cont, &enc;;
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return result;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Step 4. Insert the encoded SafeContents into the AuthenticatedSafe
|
|
Packit Service |
4684c1 |
* structure.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result = asn1_write_value(c2, "", "NEW", 1);
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (enc)
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
asn1_write_value(c2, "?LAST.contentType", ENC_DATA_OID,
|
|
Packit Service |
4684c1 |
1);
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
asn1_write_value(c2, "?LAST.contentType", DATA_OID, 1);
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (enc) {
|
|
Packit Service |
4684c1 |
/* Encrypted packets are written directly.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
asn1_write_value(c2, "?LAST.content",
|
|
Packit Service |
4684c1 |
bag->element[0].data.data,
|
|
Packit Service |
4684c1 |
bag->element[0].data.size);
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
_gnutls_x509_der_encode_and_copy(safe_cont, "", c2,
|
|
Packit Service |
4684c1 |
"?LAST.content", 1);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
asn1_delete_structure(&safe_cont);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Step 5. Re-encode and copy the AuthenticatedSafe into the pkcs12
|
|
Packit Service |
4684c1 |
* structure.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
_gnutls_x509_der_encode_and_copy(c2, "", pkcs12->pkcs12,
|
|
Packit Service |
4684c1 |
"authSafe.content", 1);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
asn1_delete_structure(&c2;;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
asn1_delete_structure(&c2;;
|
|
Packit Service |
4684c1 |
asn1_delete_structure(&safe_cont);
|
|
Packit Service |
4684c1 |
return result;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#if ENABLE_GOST
|
|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* Russian differs from PKCS#12 here. It described proprietary way
|
|
Packit Service |
4684c1 |
* to obtain MAC key instead of using standard mechanism.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* See https://wwwold.tc26.ru/standard/rs/%D0%A0%2050.1.112-2016.pdf
|
|
Packit Service |
4684c1 |
* section 5.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
_gnutls_pkcs12_gost_string_to_key(gnutls_mac_algorithm_t algo,
|
|
Packit Service |
4684c1 |
const uint8_t * salt,
|
|
Packit Service |
4684c1 |
unsigned int salt_size, unsigned int iter,
|
|
Packit Service |
4684c1 |
const char *pass, unsigned int req_keylen,
|
|
Packit Service |
4684c1 |
uint8_t * keybuf)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
uint8_t temp[96];
|
|
Packit Service |
4684c1 |
size_t temp_len = sizeof(temp);
|
|
Packit Service |
4684c1 |
gnutls_datum_t key;
|
|
Packit Service |
4684c1 |
gnutls_datum_t _salt;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (iter == 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
key.data = (void *)pass;
|
|
Packit Service |
4684c1 |
key.size = pass ? strlen(pass) : 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_salt.data = (void *)salt;
|
|
Packit Service |
4684c1 |
_salt.size = salt_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pbkdf2(algo, &key, &_salt, iter, temp, temp_len);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
memcpy(keybuf, temp + temp_len - req_keylen, req_keylen);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs12_generate_mac2:
|
|
Packit Service |
4684c1 |
* @pkcs12: A pkcs12 type
|
|
Packit Service |
4684c1 |
* @mac: the MAC algorithm to use
|
|
Packit Service |
4684c1 |
* @pass: The password for the MAC
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will generate a MAC for the PKCS12 structure.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int gnutls_pkcs12_generate_mac2(gnutls_pkcs12_t pkcs12, gnutls_mac_algorithm_t mac, const char *pass)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
uint8_t salt[8], key[MAX_HASH_SIZE];
|
|
Packit Service |
4684c1 |
int result;
|
|
Packit Service |
4684c1 |
const int iter = 10*1024;
|
|
Packit Service |
4684c1 |
mac_hd_st td1;
|
|
Packit Service |
4684c1 |
gnutls_datum_t tmp = { NULL, 0 };
|
|
Packit Service |
4684c1 |
unsigned mac_size, key_len;
|
|
Packit Service |
4684c1 |
uint8_t mac_out[MAX_HASH_SIZE];
|
|
Packit Service |
4684c1 |
const mac_entry_st *me = mac_to_entry(mac);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (pkcs12 == NULL || me == NULL)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (me->oid == NULL)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mac_size = _gnutls_mac_get_algo_len(me);
|
|
Packit Service |
4684c1 |
key_len = mac_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Generate the salt.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result = gnutls_rnd(GNUTLS_RND_NONCE, salt, sizeof(salt));
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return result;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Write the salt into the structure.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
asn1_write_value(pkcs12->pkcs12, "macData.macSalt", salt,
|
|
Packit Service |
4684c1 |
sizeof(salt));
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* write the iterations
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (iter > 1) {
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
_gnutls_x509_write_uint32(pkcs12->pkcs12,
|
|
Packit Service |
4684c1 |
"macData.iterations", iter);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Generate the key.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
#if ENABLE_GOST
|
|
Packit Service |
4684c1 |
if (me->id == GNUTLS_MAC_GOSTR_94 ||
|
|
Packit Service |
4684c1 |
me->id == GNUTLS_MAC_STREEBOG_256 ||
|
|
Packit Service |
4684c1 |
me->id == GNUTLS_MAC_STREEBOG_512) {
|
|
Packit Service |
4684c1 |
key_len = 32;
|
|
Packit Service |
4684c1 |
result = _gnutls_pkcs12_gost_string_to_key(me->id,
|
|
Packit Service |
4684c1 |
salt,
|
|
Packit Service |
4684c1 |
sizeof(salt),
|
|
Packit Service |
4684c1 |
iter,
|
|
Packit Service |
4684c1 |
pass,
|
|
Packit Service |
4684c1 |
key_len,
|
|
Packit Service |
4684c1 |
key);
|
|
Packit Service |
4684c1 |
} else
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
result = _gnutls_pkcs12_string_to_key(me, 3 /*MAC*/,
|
|
Packit Service |
4684c1 |
salt, sizeof(salt),
|
|
Packit Service |
4684c1 |
iter, pass,
|
|
Packit Service |
4684c1 |
mac_size, key);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Get the data to be MACed
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result = _decode_pkcs12_auth_safe(pkcs12->pkcs12, NULL, &tmp);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* MAC the data
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result = _gnutls_mac_init(&td1, me,
|
|
Packit Service |
4684c1 |
key, key_len);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_mac(&td1, tmp.data, tmp.size);
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&tmp);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_mac_deinit(&td1, mac_out);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
asn1_write_value(pkcs12->pkcs12, "macData.mac.digest", mac_out,
|
|
Packit Service |
4684c1 |
mac_size);
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
asn1_write_value(pkcs12->pkcs12,
|
|
Packit Service |
4684c1 |
"macData.mac.digestAlgorithm.parameters",
|
|
Packit Service |
4684c1 |
NULL, 0);
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
asn1_write_value(pkcs12->pkcs12,
|
|
Packit Service |
4684c1 |
"macData.mac.digestAlgorithm.algorithm",
|
|
Packit Service |
4684c1 |
me->oid, 1);
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&tmp);
|
|
Packit Service |
4684c1 |
return result;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs12_generate_mac:
|
|
Packit Service |
4684c1 |
* @pkcs12: A pkcs12 type
|
|
Packit Service |
4684c1 |
* @pass: The password for the MAC
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will generate a MAC for the PKCS12 structure.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int gnutls_pkcs12_generate_mac(gnutls_pkcs12_t pkcs12, const char *pass)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
return gnutls_pkcs12_generate_mac2(pkcs12, GNUTLS_MAC_SHA1, pass);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs12_verify_mac:
|
|
Packit Service |
4684c1 |
* @pkcs12: should contain a gnutls_pkcs12_t type
|
|
Packit Service |
4684c1 |
* @pass: The password for the MAC
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will verify the MAC for the PKCS12 structure.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int gnutls_pkcs12_verify_mac(gnutls_pkcs12_t pkcs12, const char *pass)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
uint8_t key[MAX_HASH_SIZE];
|
|
Packit Service |
4684c1 |
char oid[MAX_OID_SIZE];
|
|
Packit Service |
4684c1 |
int result;
|
|
Packit Service |
4684c1 |
unsigned int iter;
|
|
Packit Service |
4684c1 |
int len;
|
|
Packit Service |
4684c1 |
mac_hd_st td1;
|
|
Packit Service |
4684c1 |
gnutls_datum_t tmp = { NULL, 0 }, salt = {
|
|
Packit Service |
4684c1 |
NULL, 0};
|
|
Packit Service |
4684c1 |
uint8_t mac_output[MAX_HASH_SIZE];
|
|
Packit Service |
4684c1 |
uint8_t mac_output_orig[MAX_HASH_SIZE];
|
|
Packit Service |
4684c1 |
gnutls_mac_algorithm_t algo;
|
|
Packit Service |
4684c1 |
unsigned mac_len, key_len;
|
|
Packit Service |
4684c1 |
const mac_entry_st *entry;
|
|
Packit Service |
4684c1 |
#if ENABLE_GOST
|
|
Packit Service |
4684c1 |
int gost_retry = 0;
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (pkcs12 == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* read the iterations
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
_gnutls_x509_read_uint(pkcs12->pkcs12, "macData.iterations",
|
|
Packit Service |
4684c1 |
&iter);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
iter = 1; /* the default */
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
len = sizeof(oid);
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
asn1_read_value(pkcs12->pkcs12, "macData.mac.digestAlgorithm.algorithm",
|
|
Packit Service |
4684c1 |
oid, &len;;
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
algo = gnutls_oid_to_digest(oid);
|
|
Packit Service |
4684c1 |
if (algo == GNUTLS_MAC_UNKNOWN) {
|
|
Packit Service |
4684c1 |
unknown_mac:
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_UNKNOWN_HASH_ALGORITHM;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
entry = mac_to_entry(algo);
|
|
Packit Service |
4684c1 |
if (entry == NULL)
|
|
Packit Service |
4684c1 |
goto unknown_mac;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mac_len = _gnutls_mac_get_algo_len(entry);
|
|
Packit Service |
4684c1 |
key_len = mac_len;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Read the salt from the structure.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
_gnutls_x509_read_null_value(pkcs12->pkcs12, "macData.macSalt",
|
|
Packit Service |
4684c1 |
&salt);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Generate the key.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result = _gnutls_pkcs12_string_to_key(entry, 3 /*MAC*/,
|
|
Packit Service |
4684c1 |
salt.data, salt.size,
|
|
Packit Service |
4684c1 |
iter, pass,
|
|
Packit Service |
4684c1 |
key_len, key);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Get the data to be MACed
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result = _decode_pkcs12_auth_safe(pkcs12->pkcs12, NULL, &tmp);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#if ENABLE_GOST
|
|
Packit Service |
4684c1 |
/* GOST PKCS#12 files use either PKCS#12 scheme or proprietary
|
|
Packit Service |
4684c1 |
* HMAC-based scheme to generate MAC key. */
|
|
Packit Service |
4684c1 |
pkcs12_try_gost:
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* MAC the data
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result = _gnutls_mac_init(&td1, entry, key, key_len);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_mac(&td1, tmp.data, tmp.size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_mac_deinit(&td1, mac_output);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
len = sizeof(mac_output_orig);
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
asn1_read_value(pkcs12->pkcs12, "macData.mac.digest",
|
|
Packit Service |
4684c1 |
mac_output_orig, &len;;
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if ((unsigned)len != mac_len ||
|
|
Packit Service |
4684c1 |
memcmp(mac_output_orig, mac_output, len) != 0) {
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#if ENABLE_GOST
|
|
Packit Service |
4684c1 |
/* It is possible that GOST files use proprietary
|
|
Packit Service |
4684c1 |
* key generation scheme */
|
|
Packit Service |
4684c1 |
if (!gost_retry &&
|
|
Packit Service |
4684c1 |
(algo == GNUTLS_MAC_GOSTR_94 ||
|
|
Packit Service |
4684c1 |
algo == GNUTLS_MAC_STREEBOG_256 ||
|
|
Packit Service |
4684c1 |
algo == GNUTLS_MAC_STREEBOG_512)) {
|
|
Packit Service |
4684c1 |
gost_retry = 1;
|
|
Packit Service |
4684c1 |
key_len = 32;
|
|
Packit Service |
4684c1 |
result = _gnutls_pkcs12_gost_string_to_key(algo,
|
|
Packit Service |
4684c1 |
salt.data,
|
|
Packit Service |
4684c1 |
salt.size,
|
|
Packit Service |
4684c1 |
iter,
|
|
Packit Service |
4684c1 |
pass,
|
|
Packit Service |
4684c1 |
key_len,
|
|
Packit Service |
4684c1 |
key);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
goto pkcs12_try_gost;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = GNUTLS_E_MAC_VERIFY_FAILED;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result = 0;
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&tmp);
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&salt);
|
|
Packit Service |
4684c1 |
return result;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
write_attributes(gnutls_pkcs12_bag_t bag, int elem,
|
|
Packit Service |
4684c1 |
ASN1_TYPE c2, const char *where)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int result;
|
|
Packit Service |
4684c1 |
char root[128];
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* If the bag attributes are empty, then write
|
|
Packit Service |
4684c1 |
* nothing to the attribute field.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
if (bag->element[elem].friendly_name == NULL &&
|
|
Packit Service |
4684c1 |
bag->element[elem].local_key_id.data == NULL) {
|
|
Packit Service |
4684c1 |
/* no attributes
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result = asn1_write_value(c2, where, NULL, 0);
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (bag->element[elem].local_key_id.data != NULL) {
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Add a new Attribute
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result = asn1_write_value(c2, where, "NEW", 1);
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_str_cpy(root, sizeof(root), where);
|
|
Packit Service |
4684c1 |
_gnutls_str_cat(root, sizeof(root), ".?LAST");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
_gnutls_x509_encode_and_write_attribute(KEY_ID_OID, c2,
|
|
Packit Service |
4684c1 |
root,
|
|
Packit Service |
4684c1 |
bag->element
|
|
Packit Service |
4684c1 |
[elem].
|
|
Packit Service |
4684c1 |
local_key_id.data,
|
|
Packit Service |
4684c1 |
bag->element
|
|
Packit Service |
4684c1 |
[elem].
|
|
Packit Service |
4684c1 |
local_key_id.size,
|
|
Packit Service |
4684c1 |
1);
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return result;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (bag->element[elem].friendly_name != NULL) {
|
|
Packit Service |
4684c1 |
uint8_t *name;
|
|
Packit Service |
4684c1 |
int size, i;
|
|
Packit Service |
4684c1 |
const char *p;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Add a new Attribute
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result = asn1_write_value(c2, where, "NEW", 1);
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* convert name to BMPString
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
size = strlen(bag->element[elem].friendly_name) * 2;
|
|
Packit Service |
4684c1 |
name = gnutls_malloc(size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (name == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
p = bag->element[elem].friendly_name;
|
|
Packit Service |
4684c1 |
for (i = 0; i < size; i += 2) {
|
|
Packit Service |
4684c1 |
name[i] = 0;
|
|
Packit Service |
4684c1 |
name[i + 1] = *p;
|
|
Packit Service |
4684c1 |
p++;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_str_cpy(root, sizeof(root), where);
|
|
Packit Service |
4684c1 |
_gnutls_str_cat(root, sizeof(root), ".?LAST");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
_gnutls_x509_encode_and_write_attribute
|
|
Packit Service |
4684c1 |
(FRIENDLY_NAME_OID, c2, root, name, size, 1);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_free(name);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return result;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Encodes the bag into a SafeContents structure, and puts the output in
|
|
Packit Service |
4684c1 |
* the given datum. Enc is set to non-zero if the data are encrypted;
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
_pkcs12_encode_safe_contents(gnutls_pkcs12_bag_t bag, ASN1_TYPE * contents,
|
|
Packit Service |
4684c1 |
int *enc)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
|
|
Packit Service |
4684c1 |
int result;
|
|
Packit Service |
4684c1 |
unsigned i;
|
|
Packit Service |
4684c1 |
const char *oid;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (bag->element[0].type == GNUTLS_BAG_ENCRYPTED && enc) {
|
|
Packit Service |
4684c1 |
*enc = 1;
|
|
Packit Service |
4684c1 |
return 0; /* ENCRYPTED BAG, do nothing. */
|
|
Packit Service |
4684c1 |
} else if (enc)
|
|
Packit Service |
4684c1 |
*enc = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Step 1. Create the SEQUENCE.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if ((result = asn1_create_element
|
|
Packit Service |
4684c1 |
(_gnutls_get_pkix(), "PKIX1.pkcs-12-SafeContents",
|
|
Packit Service |
4684c1 |
&c2)) != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i = 0; i < bag->bag_elements; i++) {
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
oid = bag_to_oid(bag->element[i].type);
|
|
Packit Service |
4684c1 |
if (oid == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
continue;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result = asn1_write_value(c2, "", "NEW", 1);
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Copy the bag type.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result = asn1_write_value(c2, "?LAST.bagId", oid, 1);
|
|
Packit Service |
4684c1 |
if (result != ASN1_SUCCESS) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
result = _gnutls_asn2err(result);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Set empty attributes
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
write_attributes(bag, i, c2, "?LAST.bagAttributes");
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Copy the Bag Value
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (bag->element[i].type == GNUTLS_BAG_CERTIFICATE ||
|
|
Packit Service |
4684c1 |
bag->element[i].type == GNUTLS_BAG_SECRET ||
|
|
Packit Service |
4684c1 |
bag->element[i].type == GNUTLS_BAG_CRL) {
|
|
Packit Service |
4684c1 |
gnutls_datum_t tmp;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* in that case encode it to a CertBag or
|
|
Packit Service |
4684c1 |
* a CrlBag.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
_pkcs12_encode_crt_bag(bag->element[i].type,
|
|
Packit Service |
4684c1 |
&bag->element[i].data,
|
|
Packit Service |
4684c1 |
&tmp);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
_gnutls_x509_write_value(c2, "?LAST.bagValue",
|
|
Packit Service |
4684c1 |
&tmp);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&tmp);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
result =
|
|
Packit Service |
4684c1 |
_gnutls_x509_write_value(c2, "?LAST.bagValue",
|
|
Packit Service |
4684c1 |
&bag->element[i].
|
|
Packit Service |
4684c1 |
data);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (result < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Encode the data and copy them into the datum
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
*contents = c2;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
if (c2)
|
|
Packit Service |
4684c1 |
asn1_delete_structure(&c2;;
|
|
Packit Service |
4684c1 |
return result;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Checks if the extra_certs contain certificates that may form a chain
|
|
Packit Service |
4684c1 |
* with the first certificate in chain (it is expected that chain_len==1)
|
|
Packit Service |
4684c1 |
* and appends those in the chain.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
static int make_chain(gnutls_x509_crt_t ** chain, unsigned int *chain_len,
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_t ** extra_certs,
|
|
Packit Service |
4684c1 |
unsigned int *extra_certs_len, unsigned int flags)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
unsigned int i;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (*chain_len != 1)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
i = 0;
|
|
Packit Service |
4684c1 |
while (i < *extra_certs_len) {
|
|
Packit Service |
4684c1 |
/* if it is an issuer but not a self-signed one */
|
|
Packit Service |
4684c1 |
if (gnutls_x509_crt_check_issuer
|
|
Packit Service |
4684c1 |
((*chain)[*chain_len - 1], (*extra_certs)[i]) != 0) {
|
|
Packit Service |
4684c1 |
if (!(flags & GNUTLS_PKCS12_SP_INCLUDE_SELF_SIGNED)
|
|
Packit Service |
4684c1 |
&&
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_check_issuer((*extra_certs)[i],
|
|
Packit Service |
4684c1 |
(*extra_certs)[i])
|
|
Packit Service |
4684c1 |
!= 0)
|
|
Packit Service |
4684c1 |
goto skip;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
*chain =
|
|
Packit Service |
4684c1 |
gnutls_realloc_fast(*chain,
|
|
Packit Service |
4684c1 |
sizeof((*chain)[0]) *
|
|
Packit Service |
4684c1 |
++(*chain_len));
|
|
Packit Service |
4684c1 |
if (*chain == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
(*chain)[*chain_len - 1] = (*extra_certs)[i];
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
(*extra_certs)[i] =
|
|
Packit Service |
4684c1 |
(*extra_certs)[*extra_certs_len - 1];
|
|
Packit Service |
4684c1 |
(*extra_certs_len)--;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
i = 0;
|
|
Packit Service |
4684c1 |
continue;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
skip:
|
|
Packit Service |
4684c1 |
i++;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs12_simple_parse:
|
|
Packit Service |
4684c1 |
* @p12: A pkcs12 type
|
|
Packit Service |
4684c1 |
* @password: optional password used to decrypt the structure, bags and keys.
|
|
Packit Service |
4684c1 |
* @key: a structure to store the parsed private key.
|
|
Packit Service |
4684c1 |
* @chain: the corresponding to key certificate chain (may be %NULL)
|
|
Packit Service |
4684c1 |
* @chain_len: will be updated with the number of additional (may be %NULL)
|
|
Packit Service |
4684c1 |
* @extra_certs: optional pointer to receive an array of additional
|
|
Packit Service |
4684c1 |
* certificates found in the PKCS12 structure (may be %NULL).
|
|
Packit Service |
4684c1 |
* @extra_certs_len: will be updated with the number of additional
|
|
Packit Service |
4684c1 |
* certs (may be %NULL).
|
|
Packit Service |
4684c1 |
* @crl: an optional structure to store the parsed CRL (may be %NULL).
|
|
Packit Service |
4684c1 |
* @flags: should be zero or one of GNUTLS_PKCS12_SP_*
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function parses a PKCS12 structure in @pkcs12 and extracts the
|
|
Packit Service |
4684c1 |
* private key, the corresponding certificate chain, any additional
|
|
Packit Service |
4684c1 |
* certificates and a CRL. The structures in @key, @chain @crl, and @extra_certs
|
|
Packit Service |
4684c1 |
* must not be initialized.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* The @extra_certs and @extra_certs_len parameters are optional
|
|
Packit Service |
4684c1 |
* and both may be set to %NULL. If either is non-%NULL, then both must
|
|
Packit Service |
4684c1 |
* be set. The value for @extra_certs is allocated
|
|
Packit Service |
4684c1 |
* using gnutls_malloc().
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Encrypted PKCS12 bags and PKCS8 private keys are supported, but
|
|
Packit Service |
4684c1 |
* only with password based security and the same password for all
|
|
Packit Service |
4684c1 |
* operations.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Note that a PKCS12 structure may contain many keys and/or certificates,
|
|
Packit Service |
4684c1 |
* and there is no way to identify which key/certificate pair you want.
|
|
Packit Service |
4684c1 |
* For this reason this function is useful for PKCS12 files that contain
|
|
Packit Service |
4684c1 |
* only one key/certificate pair and/or one CRL.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* If the provided structure has encrypted fields but no password
|
|
Packit Service |
4684c1 |
* is provided then this function returns %GNUTLS_E_DECRYPTION_FAILED.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Note that normally the chain constructed does not include self signed
|
|
Packit Service |
4684c1 |
* certificates, to comply with TLS' requirements. If, however, the flag
|
|
Packit Service |
4684c1 |
* %GNUTLS_PKCS12_SP_INCLUDE_SELF_SIGNED is specified then
|
|
Packit Service |
4684c1 |
* self signed certificates will be included in the chain.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Prior to using this function the PKCS #12 structure integrity must
|
|
Packit Service |
4684c1 |
* be verified using gnutls_pkcs12_verify_mac().
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
4684c1 |
* negative error value.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.1.0
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
gnutls_pkcs12_simple_parse(gnutls_pkcs12_t p12,
|
|
Packit Service |
4684c1 |
const char *password,
|
|
Packit Service |
4684c1 |
gnutls_x509_privkey_t * key,
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_t ** chain,
|
|
Packit Service |
4684c1 |
unsigned int *chain_len,
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_t ** extra_certs,
|
|
Packit Service |
4684c1 |
unsigned int *extra_certs_len,
|
|
Packit Service |
4684c1 |
gnutls_x509_crl_t * crl, unsigned int flags)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
gnutls_pkcs12_bag_t bag = NULL;
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_t *_extra_certs = NULL;
|
|
Packit Service |
4684c1 |
unsigned int _extra_certs_len = 0;
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_t *_chain = NULL;
|
|
Packit Service |
4684c1 |
unsigned int _chain_len = 0;
|
|
Packit Service |
4684c1 |
int idx = 0;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
size_t cert_id_size = 0;
|
|
Packit Service |
4684c1 |
size_t key_id_size = 0;
|
|
Packit Service |
4684c1 |
uint8_t cert_id[20];
|
|
Packit Service |
4684c1 |
uint8_t key_id[20];
|
|
Packit Service |
4684c1 |
int privkey_ok = 0;
|
|
Packit Service |
4684c1 |
unsigned int i;
|
|
Packit Service |
4684c1 |
int elements_in_bag;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
*key = NULL;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (crl)
|
|
Packit Service |
4684c1 |
*crl = NULL;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* find the first private key */
|
|
Packit Service |
4684c1 |
for (;;) {
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pkcs12_bag_init(&bag;;
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
bag = NULL;
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pkcs12_get_bag(p12, idx, bag);
|
|
Packit Service |
4684c1 |
if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
|
|
Packit Service |
4684c1 |
gnutls_pkcs12_bag_deinit(bag);
|
|
Packit Service |
4684c1 |
bag = NULL;
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pkcs12_bag_get_type(bag, 0);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret == GNUTLS_BAG_ENCRYPTED) {
|
|
Packit Service |
4684c1 |
if (password == NULL) {
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
gnutls_assert_val
|
|
Packit Service |
4684c1 |
(GNUTLS_E_DECRYPTION_FAILED);
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pkcs12_bag_decrypt(bag, password);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
elements_in_bag = gnutls_pkcs12_bag_get_count(bag);
|
|
Packit Service |
4684c1 |
if (elements_in_bag < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i = 0; i < (unsigned)elements_in_bag; i++) {
|
|
Packit Service |
4684c1 |
int type;
|
|
Packit Service |
4684c1 |
gnutls_datum_t data;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
type = gnutls_pkcs12_bag_get_type(bag, i);
|
|
Packit Service |
4684c1 |
if (type < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pkcs12_bag_get_data(bag, i, &data);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
switch (type) {
|
|
Packit Service |
4684c1 |
case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
|
|
Packit Service |
4684c1 |
if (password == NULL) {
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
gnutls_assert_val
|
|
Packit Service |
4684c1 |
(GNUTLS_E_DECRYPTION_FAILED);
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case GNUTLS_BAG_PKCS8_KEY:
|
|
Packit Service |
4684c1 |
if (*key != NULL) { /* too simple to continue */
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_x509_privkey_init(key);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_x509_privkey_import_pkcs8
|
|
Packit Service |
4684c1 |
(*key, &data, GNUTLS_X509_FMT_DER,
|
|
Packit Service |
4684c1 |
password,
|
|
Packit Service |
4684c1 |
type ==
|
|
Packit Service |
4684c1 |
GNUTLS_BAG_PKCS8_KEY ?
|
|
Packit Service |
4684c1 |
GNUTLS_PKCS_PLAIN : 0);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
key_id_size = sizeof(key_id);
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
gnutls_x509_privkey_get_key_id(*key, 0,
|
|
Packit Service |
4684c1 |
key_id,
|
|
Packit Service |
4684c1 |
&key_id_size);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
privkey_ok = 1; /* break */
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
default:
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
idx++;
|
|
Packit Service |
4684c1 |
gnutls_pkcs12_bag_deinit(bag);
|
|
Packit Service |
4684c1 |
bag = NULL;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (privkey_ok != 0) /* private key was found */
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (privkey_ok == 0) { /* no private key */
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* now find the corresponding certificate
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
idx = 0;
|
|
Packit Service |
4684c1 |
bag = NULL;
|
|
Packit Service |
4684c1 |
for (;;) {
|
|
Packit Service |
4684c1 |
ret = gnutls_pkcs12_bag_init(&bag;;
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
bag = NULL;
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pkcs12_get_bag(p12, idx, bag);
|
|
Packit Service |
4684c1 |
if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
|
|
Packit Service |
4684c1 |
gnutls_pkcs12_bag_deinit(bag);
|
|
Packit Service |
4684c1 |
bag = NULL;
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pkcs12_bag_get_type(bag, 0);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret == GNUTLS_BAG_ENCRYPTED) {
|
|
Packit Service |
4684c1 |
ret = gnutls_pkcs12_bag_decrypt(bag, password);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
elements_in_bag = gnutls_pkcs12_bag_get_count(bag);
|
|
Packit Service |
4684c1 |
if (elements_in_bag < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i = 0; i < (unsigned)elements_in_bag; i++) {
|
|
Packit Service |
4684c1 |
int type;
|
|
Packit Service |
4684c1 |
gnutls_datum_t data;
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_t this_cert;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
type = gnutls_pkcs12_bag_get_type(bag, i);
|
|
Packit Service |
4684c1 |
if (type < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_pkcs12_bag_get_data(bag, i, &data);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
switch (type) {
|
|
Packit Service |
4684c1 |
case GNUTLS_BAG_CERTIFICATE:
|
|
Packit Service |
4684c1 |
ret = gnutls_x509_crt_init(&this_cert);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_import(this_cert,
|
|
Packit Service |
4684c1 |
&data,
|
|
Packit Service |
4684c1 |
GNUTLS_X509_FMT_DER);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_deinit(this_cert);
|
|
Packit Service |
4684c1 |
this_cert = NULL;
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* check if the key id match */
|
|
Packit Service |
4684c1 |
cert_id_size = sizeof(cert_id);
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_get_key_id(this_cert,
|
|
Packit Service |
4684c1 |
0, cert_id,
|
|
Packit Service |
4684c1 |
&cert_id_size);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_deinit(this_cert);
|
|
Packit Service |
4684c1 |
this_cert = NULL;
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (memcmp(cert_id, key_id, cert_id_size) != 0) { /* they don't match - skip the certificate */
|
|
Packit Service |
4684c1 |
_extra_certs =
|
|
Packit Service |
4684c1 |
gnutls_realloc_fast
|
|
Packit Service |
4684c1 |
(_extra_certs,
|
|
Packit Service |
4684c1 |
sizeof(_extra_certs
|
|
Packit Service |
4684c1 |
[0]) *
|
|
Packit Service |
4684c1 |
++_extra_certs_len);
|
|
Packit Service |
4684c1 |
if (!_extra_certs) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
GNUTLS_E_MEMORY_ERROR;
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
_extra_certs
|
|
Packit Service |
4684c1 |
[_extra_certs_len -
|
|
Packit Service |
4684c1 |
1] = this_cert;
|
|
Packit Service |
4684c1 |
this_cert = NULL;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
if (chain && _chain_len == 0) {
|
|
Packit Service |
4684c1 |
_chain =
|
|
Packit Service |
4684c1 |
gnutls_malloc(sizeof
|
|
Packit Service |
4684c1 |
(_chain
|
|
Packit Service |
4684c1 |
[0]) *
|
|
Packit Service |
4684c1 |
(++_chain_len));
|
|
Packit Service |
4684c1 |
if (!_chain) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
GNUTLS_E_MEMORY_ERROR;
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
_chain[_chain_len - 1] =
|
|
Packit Service |
4684c1 |
this_cert;
|
|
Packit Service |
4684c1 |
this_cert = NULL;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_deinit
|
|
Packit Service |
4684c1 |
(this_cert);
|
|
Packit Service |
4684c1 |
this_cert = NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
case GNUTLS_BAG_CRL:
|
|
Packit Service |
4684c1 |
if (crl == NULL || *crl != NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_x509_crl_init(crl);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
gnutls_x509_crl_import(*crl, &data,
|
|
Packit Service |
4684c1 |
GNUTLS_X509_FMT_DER);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
gnutls_x509_crl_deinit(*crl);
|
|
Packit Service |
4684c1 |
*crl = NULL;
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
case GNUTLS_BAG_ENCRYPTED:
|
|
Packit Service |
4684c1 |
/* XXX Bother to recurse one level down? Unlikely to
|
|
Packit Service |
4684c1 |
use the same password anyway. */
|
|
Packit Service |
4684c1 |
case GNUTLS_BAG_EMPTY:
|
|
Packit Service |
4684c1 |
default:
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
idx++;
|
|
Packit Service |
4684c1 |
gnutls_pkcs12_bag_deinit(bag);
|
|
Packit Service |
4684c1 |
bag = NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (chain != NULL) {
|
|
Packit Service |
4684c1 |
if (_chain_len != 1) {
|
|
Packit Service |
4684c1 |
ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
make_chain(&_chain, &_chain_len, &_extra_certs,
|
|
Packit Service |
4684c1 |
&_extra_certs_len, flags);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
done:
|
|
Packit Service |
4684c1 |
if (bag)
|
|
Packit Service |
4684c1 |
gnutls_pkcs12_bag_deinit(bag);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
if (*key) {
|
|
Packit Service |
4684c1 |
gnutls_x509_privkey_deinit(*key);
|
|
Packit Service |
4684c1 |
*key = NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
if (crl != NULL && *crl != NULL) {
|
|
Packit Service |
4684c1 |
gnutls_x509_crl_deinit(*crl);
|
|
Packit Service |
4684c1 |
*crl = NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
if (_extra_certs_len && _extra_certs != NULL) {
|
|
Packit Service |
4684c1 |
for (i = 0; i < _extra_certs_len; i++)
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_deinit(_extra_certs[i]);
|
|
Packit Service |
4684c1 |
gnutls_free(_extra_certs);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
if (_chain_len && _chain != NULL) {
|
|
Packit Service |
4684c1 |
for (i = 0; i < _chain_len; i++)
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_deinit(_chain[i]);
|
|
Packit Service |
4684c1 |
gnutls_free(_chain);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (extra_certs && _extra_certs_len > 0) {
|
|
Packit Service |
4684c1 |
*extra_certs = _extra_certs;
|
|
Packit Service |
4684c1 |
*extra_certs_len = _extra_certs_len;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
if (extra_certs) {
|
|
Packit Service |
4684c1 |
*extra_certs = NULL;
|
|
Packit Service |
4684c1 |
*extra_certs_len = 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
for (i = 0; i < _extra_certs_len; i++)
|
|
Packit Service |
4684c1 |
gnutls_x509_crt_deinit(_extra_certs[i]);
|
|
Packit Service |
4684c1 |
gnutls_free(_extra_certs);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (chain != NULL) {
|
|
Packit Service |
4684c1 |
*chain = _chain;
|
|
Packit Service |
4684c1 |
*chain_len = _chain_len;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_pkcs12_mac_info:
|
|
Packit Service |
4684c1 |
* @pkcs12: A pkcs12 type
|
|
Packit Service |
4684c1 |
* @mac: the MAC algorithm used as %gnutls_mac_algorithm_t
|
|
Packit Service |
4684c1 |
* @salt: the salt used for string to key (if non-NULL then @salt_size initially holds its size)
|
|
Packit Service |
4684c1 |
* @salt_size: string to key salt size
|
|
Packit Service |
4684c1 |
* @iter_count: string to key iteration count
|
|
Packit Service |
4684c1 |
* @oid: if non-NULL it will contain an allocated null-terminated variable with the OID
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will provide information on the MAC algorithm used
|
|
Packit Service |
4684c1 |
* in a PKCS #12 structure. If the structure algorithms
|
|
Packit Service |
4684c1 |
* are unknown the code %GNUTLS_E_UNKNOWN_HASH_ALGORITHM will be returned,
|
|
Packit Service |
4684c1 |
* and only @oid, will be set. That is, @oid will be set on structures
|
|
Packit Service |
4684c1 |
* with a MAC whether supported or not. It must be deinitialized using gnutls_free().
|
|
Packit Service |
4684c1 |
* The other variables are only set on supported structures.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: %GNUTLS_E_INVALID_REQUEST if the provided structure doesn't contain a MAC,
|
|
Packit Service |
4684c1 |
* %GNUTLS_E_UNKNOWN_HASH_ALGORITHM if the structure's MAC isn't supported, or
|
|
Packit Service |
4684c1 |
* another negative error code in case of a failure. Zero on success.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
gnutls_pkcs12_mac_info(gnutls_pkcs12_t pkcs12, unsigned int *mac,
|
|
Packit Service |
4684c1 |
void *salt, unsigned int *salt_size, unsigned int *iter_count, char **oid)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
gnutls_datum_t tmp = { NULL, 0 }, dsalt = {
|
|
Packit Service |
4684c1 |
NULL, 0};
|
|
Packit Service |
4684c1 |
gnutls_mac_algorithm_t algo;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (oid)
|
|
Packit Service |
4684c1 |
*oid = NULL;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (pkcs12 == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_x509_read_value(pkcs12->pkcs12, "macData.mac.digestAlgorithm.algorithm",
|
|
Packit Service |
4684c1 |
&tmp);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (oid) {
|
|
Packit Service |
4684c1 |
*oid = (char*)tmp.data;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
algo = gnutls_oid_to_digest((char*)tmp.data);
|
|
Packit Service |
4684c1 |
if (algo == GNUTLS_MAC_UNKNOWN || mac_to_entry(algo) == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_UNKNOWN_HASH_ALGORITHM;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (oid) {
|
|
Packit Service |
4684c1 |
tmp.data = NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (mac) {
|
|
Packit Service |
4684c1 |
*mac = algo;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (iter_count) {
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_x509_read_uint(pkcs12->pkcs12, "macData.iterations",
|
|
Packit Service |
4684c1 |
iter_count);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
*iter_count = 1; /* the default */
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (salt) {
|
|
Packit Service |
4684c1 |
/* Read the salt from the structure.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_x509_read_null_value(pkcs12->pkcs12, "macData.macSalt",
|
|
Packit Service |
4684c1 |
&dsalt);
|
|
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 |
if (*salt_size >= (unsigned)dsalt.size) {
|
|
Packit Service |
4684c1 |
*salt_size = dsalt.size;
|
|
Packit Service |
4684c1 |
if (dsalt.size > 0)
|
|
Packit Service |
4684c1 |
memcpy(salt, dsalt.data, dsalt.size);
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
*salt_size = dsalt.size;
|
|
Packit Service |
4684c1 |
ret = gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = 0;
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&tmp);
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&dsalt);
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|