|
Packit |
aea12f |
/*
|
|
Packit |
aea12f |
* Copyright (C) 2015 Red Hat, Inc.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Author: Nikos Mavrogiannopoulos
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This file is part of GnuTLS.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* The GnuTLS is free software; you can redistribute it and/or
|
|
Packit |
aea12f |
* modify it under the terms of the GNU Lesser General Public License
|
|
Packit |
aea12f |
* as published by the Free Software Foundation; either version 2.1 of
|
|
Packit |
aea12f |
* the License, or (at your option) any later version.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This library is distributed in the hope that it will be useful, but
|
|
Packit |
aea12f |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
aea12f |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
aea12f |
* Lesser General Public License for more details.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit |
aea12f |
* along with this program. If not, see <https://www.gnu.org/licenses/>
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#include "gnutls_int.h"
|
|
Packit |
aea12f |
#include <common.h>
|
|
Packit |
aea12f |
#include <x509.h>
|
|
Packit |
aea12f |
#include <x509_int.h>
|
|
Packit |
aea12f |
#include <num.h>
|
|
Packit |
aea12f |
#include "errors.h"
|
|
Packit |
aea12f |
#include <extras/randomart.h>
|
|
Packit |
aea12f |
#include <pkcs7_int.h>
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#define addf _gnutls_buffer_append_printf
|
|
Packit |
aea12f |
#define adds _gnutls_buffer_append_str
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
static void print_dn(gnutls_buffer_st * str, const char *prefix,
|
|
Packit |
aea12f |
const gnutls_datum_t * raw)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
gnutls_x509_dn_t dn = NULL;
|
|
Packit |
aea12f |
gnutls_datum_t output = { NULL, 0 };
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = gnutls_x509_dn_init(&dn;;
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
addf(str, "%s: [error]\n", prefix);
|
|
Packit |
aea12f |
return;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = gnutls_x509_dn_import(dn, raw);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
addf(str, "%s: [error]\n", prefix);
|
|
Packit |
aea12f |
goto cleanup;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = gnutls_x509_dn_get_str2(dn, &output, 0);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
addf(str, "%s: [error]\n", prefix);
|
|
Packit |
aea12f |
goto cleanup;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
addf(str, "%s: %s\n", prefix, output.data);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
cleanup:
|
|
Packit |
aea12f |
gnutls_x509_dn_deinit(dn);
|
|
Packit |
aea12f |
gnutls_free(output.data);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit Service |
991b93 |
/* Do not encode ASN1 and type for now */
|
|
Packit Service |
991b93 |
#define ENTRY(oid, name, type) {oid, sizeof(oid)-1, name, sizeof(name)-1, NULL, type}
|
|
Packit Service |
991b93 |
#define ENTRY2(oid, name) {oid, sizeof(oid)-1, name, sizeof(name)-1, NULL, ASN1_ETYPE_INVALID}
|
|
Packit Service |
991b93 |
|
|
Packit Service |
991b93 |
static const struct oid_to_string pkcs7_attrs[] = {
|
|
Packit Service |
991b93 |
ENTRY ("1.2.840.113549.1.9.3", "contentType", ASN1_ETYPE_OBJECT_ID),
|
|
Packit Service |
991b93 |
ENTRY ("1.2.840.113549.1.9.4", "messageDigest", ASN1_ETYPE_OCTET_STRING),
|
|
Packit Service |
991b93 |
ENTRY ("1.2.840.113549.1.9.5", "signingTime", ASN1_ETYPE_INVALID),
|
|
Packit Service |
991b93 |
ENTRY2("1.2.840.113549.1.9.6", "countersignature"),
|
|
Packit Service |
991b93 |
ENTRY2("1.2.840.113549.1.9.15", "smimeCapabilities"),
|
|
Packit Service |
991b93 |
|
|
Packit Service |
991b93 |
ENTRY2("1.2.840.113549.1.9.16.2.1", "aa-receiptRequest"),
|
|
Packit Service |
991b93 |
ENTRY2("1.2.840.113549.1.9.16.2.2", "aa-securityLabel"),
|
|
Packit Service |
991b93 |
ENTRY2("1.2.840.113549.1.9.16.2.3", "aa-mlExpandHistory"),
|
|
Packit Service |
991b93 |
ENTRY2("1.2.840.113549.1.9.16.2.4", "aa-contentHint"),
|
|
Packit Service |
991b93 |
ENTRY2("1.2.840.113549.1.9.16.2.9", "aa-equivalentLabels"),
|
|
Packit Service |
991b93 |
ENTRY2("1.2.840.113549.1.9.16.2.10", "aa-contentReference"),
|
|
Packit Service |
991b93 |
ENTRY2("1.2.840.113549.1.9.16.2.11", "aa-encrypKeyPref"),
|
|
Packit Service |
991b93 |
ENTRY2("1.2.840.113549.1.9.16.2.12", "aa-signingCertificate"),
|
|
Packit Service |
991b93 |
ENTRY2("1.2.840.113549.1.9.16.2.19", "aa-ets-otherSigCert"),
|
|
Packit Service |
991b93 |
ENTRY2("1.2.840.113549.1.9.16.2.47", "aa-signingCertificateV2"),
|
|
Packit Service |
991b93 |
|
|
Packit Service |
991b93 |
{NULL, 0, NULL, 0, NULL, 0}
|
|
Packit Service |
991b93 |
};
|
|
Packit Service |
991b93 |
|
|
Packit |
aea12f |
static void print_raw(gnutls_buffer_st * str, const char *prefix,
|
|
Packit |
aea12f |
const gnutls_datum_t * raw)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
gnutls_datum_t result;
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (raw->data == NULL || raw->size == 0)
|
|
Packit |
aea12f |
return;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = gnutls_hex_encode2(raw, &result);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
addf(str, "%s: [error]\n", prefix);
|
|
Packit |
aea12f |
return;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
addf(str, "%s: %s\n", prefix, result.data);
|
|
Packit |
aea12f |
gnutls_free(result.data);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
static void print_pkcs7_info(gnutls_pkcs7_signature_info_st * info,
|
|
Packit |
aea12f |
gnutls_buffer_st * str,
|
|
Packit |
aea12f |
gnutls_certificate_print_formats_t format)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
unsigned i;
|
|
Packit |
aea12f |
char *oid;
|
|
Packit |
aea12f |
gnutls_datum_t data;
|
|
Packit |
aea12f |
char prefix[128];
|
|
Packit |
aea12f |
char s[42];
|
|
Packit |
aea12f |
size_t max;
|
|
Packit |
aea12f |
int ret;
|
|
Packit Service |
991b93 |
const struct oid_to_string * entry;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (info->issuer_dn.size > 0)
|
|
Packit |
aea12f |
print_dn(str, "\tSigner's issuer DN", &info->issuer_dn);
|
|
Packit |
aea12f |
print_raw(str, "\tSigner's serial", &info->signer_serial);
|
|
Packit |
aea12f |
print_raw(str, "\tSigner's issuer key ID", &info->issuer_keyid);
|
|
Packit |
aea12f |
if (info->signing_time != -1) {
|
|
Packit |
aea12f |
struct tm t;
|
|
Packit |
aea12f |
if (gmtime_r(&info->signing_time, &t) == NULL) {
|
|
Packit |
aea12f |
addf(str, "error: gmtime_r (%ld)\n",
|
|
Packit |
aea12f |
(unsigned long)info->signing_time);
|
|
Packit |
aea12f |
} else {
|
|
Packit |
aea12f |
max = sizeof(s);
|
|
Packit |
aea12f |
if (strftime(s, max, "%a %b %d %H:%M:%S UTC %Y", &t) ==
|
|
Packit |
aea12f |
0) {
|
|
Packit |
aea12f |
addf(str, "error: strftime (%ld)\n",
|
|
Packit |
aea12f |
(unsigned long)info->signing_time);
|
|
Packit |
aea12f |
} else {
|
|
Packit |
aea12f |
addf(str, "\tSigning time: %s\n", s);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
addf(str, "\tSignature Algorithm: %s\n",
|
|
Packit |
aea12f |
gnutls_sign_get_name(info->algo));
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (format == GNUTLS_CRT_PRINT_FULL) {
|
|
Packit |
aea12f |
if (info->signed_attrs) {
|
|
Packit |
aea12f |
for (i = 0;; i++) {
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
gnutls_pkcs7_get_attr(info->signed_attrs, i,
|
|
Packit |
aea12f |
&oid, &data, 0);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
break;
|
|
Packit |
aea12f |
if (i == 0)
|
|
Packit |
aea12f |
addf(str, "\tSigned Attributes:\n");
|
|
Packit |
aea12f |
|
|
Packit Service |
991b93 |
entry = _gnutls_oid_get_entry(pkcs7_attrs, oid);
|
|
Packit Service |
991b93 |
snprintf(prefix, sizeof(prefix), "\t\t%s",
|
|
Packit Service |
991b93 |
(entry && entry->name_desc) ? entry->name_desc : oid);
|
|
Packit |
aea12f |
print_raw(str, prefix, &data);
|
|
Packit |
aea12f |
gnutls_free(data.data);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
if (info->unsigned_attrs) {
|
|
Packit |
aea12f |
for (i = 0;; i++) {
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
gnutls_pkcs7_get_attr(info->unsigned_attrs,
|
|
Packit |
aea12f |
i, &oid, &data, 0);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
break;
|
|
Packit |
aea12f |
if (i == 0)
|
|
Packit |
aea12f |
addf(str, "\tUnsigned Attributes:\n");
|
|
Packit |
aea12f |
|
|
Packit Service |
991b93 |
entry = _gnutls_oid_get_entry(pkcs7_attrs, oid);
|
|
Packit Service |
991b93 |
snprintf(prefix, sizeof(prefix), "\t\t%s",
|
|
Packit Service |
991b93 |
(entry && entry->name_desc) ? entry->name_desc : oid);
|
|
Packit |
aea12f |
print_raw(str, prefix, &data);
|
|
Packit |
aea12f |
gnutls_free(data.data);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
adds(str, "\n");
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/**
|
|
Packit Service |
991b93 |
* gnutls_pkcs7_print_signature_info:
|
|
Packit Service |
991b93 |
* @info: The PKCS7 signature info struct to be printed
|
|
Packit Service |
991b93 |
* @format: Indicate the format to use
|
|
Packit Service |
991b93 |
* @out: Newly allocated datum with null terminated string.
|
|
Packit Service |
991b93 |
*
|
|
Packit Service |
991b93 |
* This function will pretty print a PKCS #7 signature info structure, suitable
|
|
Packit Service |
991b93 |
* for display to a human.
|
|
Packit Service |
991b93 |
*
|
|
Packit Service |
991b93 |
* Currently the supported formats are %GNUTLS_CRT_PRINT_FULL and
|
|
Packit Service |
991b93 |
* %GNUTLS_CRT_PRINT_COMPACT.
|
|
Packit Service |
991b93 |
*
|
|
Packit Service |
991b93 |
* The output @out needs to be deallocated using gnutls_free().
|
|
Packit Service |
991b93 |
*
|
|
Packit Service |
991b93 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit Service |
991b93 |
* negative error value.
|
|
Packit Service |
991b93 |
*
|
|
Packit Service |
991b93 |
* Since: 3.6.14
|
|
Packit Service |
991b93 |
**/
|
|
Packit Service |
991b93 |
int gnutls_pkcs7_print_signature_info(gnutls_pkcs7_signature_info_st * info,
|
|
Packit Service |
991b93 |
gnutls_certificate_print_formats_t format,
|
|
Packit Service |
991b93 |
gnutls_datum_t * out)
|
|
Packit Service |
991b93 |
{
|
|
Packit Service |
991b93 |
gnutls_buffer_st str;
|
|
Packit Service |
991b93 |
|
|
Packit Service |
991b93 |
_gnutls_buffer_init(&str);
|
|
Packit Service |
991b93 |
print_pkcs7_info(info, &str, format);
|
|
Packit Service |
991b93 |
|
|
Packit Service |
991b93 |
return _gnutls_buffer_to_datum(&str, out, 1);
|
|
Packit Service |
991b93 |
}
|
|
Packit Service |
991b93 |
|
|
Packit Service |
991b93 |
/**
|
|
Packit |
aea12f |
* gnutls_pkcs7_crt_print:
|
|
Packit |
aea12f |
* @pkcs7: The PKCS7 struct to be printed
|
|
Packit |
aea12f |
* @format: Indicate the format to use
|
|
Packit |
aea12f |
* @out: Newly allocated datum with null terminated string.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This function will pretty print a signed PKCS #7 structure, suitable for
|
|
Packit |
aea12f |
* display to a human.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Currently the supported formats are %GNUTLS_CRT_PRINT_FULL and
|
|
Packit |
aea12f |
* %GNUTLS_CRT_PRINT_COMPACT.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* The output @out needs to be deallocated using gnutls_free().
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
|
|
Packit |
aea12f |
* negative error value.
|
|
Packit |
aea12f |
**/
|
|
Packit |
aea12f |
int gnutls_pkcs7_print(gnutls_pkcs7_t pkcs7,
|
|
Packit |
aea12f |
gnutls_certificate_print_formats_t format,
|
|
Packit |
aea12f |
gnutls_datum_t * out)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
int count, ret, i;
|
|
Packit |
aea12f |
gnutls_pkcs7_signature_info_st info;
|
|
Packit |
aea12f |
gnutls_buffer_st str;
|
|
Packit |
aea12f |
const char *oid;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
_gnutls_buffer_init(&str);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* For backwards compatibility with structures using the default OID,
|
|
Packit |
aea12f |
* we don't print the eContent Type explicitly */
|
|
Packit |
aea12f |
oid = gnutls_pkcs7_get_embedded_data_oid(pkcs7);
|
|
Packit |
aea12f |
if (oid) {
|
|
Packit |
aea12f |
if (strcmp(oid, DATA_OID) != 0
|
|
Packit |
aea12f |
&& strcmp(oid, DIGESTED_DATA_OID) != 0) {
|
|
Packit |
aea12f |
addf(&str, "eContent Type: %s\n", oid);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
for (i = 0;; i++) {
|
|
Packit |
aea12f |
if (i == 0)
|
|
Packit |
aea12f |
addf(&str, "Signers:\n");
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = gnutls_pkcs7_get_signature_info(pkcs7, i, &info;;
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
break;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
print_pkcs7_info(&info, &str, format);
|
|
Packit |
aea12f |
gnutls_pkcs7_signature_info_deinit(&info;;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (format == GNUTLS_CRT_PRINT_FULL) {
|
|
Packit |
aea12f |
gnutls_datum_t data, b64;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
count = gnutls_pkcs7_get_crt_count(pkcs7);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (count > 0) {
|
|
Packit |
aea12f |
addf(&str, "Number of certificates: %u\n\n",
|
|
Packit |
aea12f |
count);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
for (i = 0; i < count; i++) {
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
gnutls_pkcs7_get_crt_raw2(pkcs7, i, &data);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
addf(&str,
|
|
Packit |
aea12f |
"Error: cannot print certificate %d\n",
|
|
Packit |
aea12f |
i);
|
|
Packit |
aea12f |
continue;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
gnutls_pem_base64_encode_alloc
|
|
Packit |
aea12f |
("CERTIFICATE", &data, &b64);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_free(data.data);
|
|
Packit |
aea12f |
continue;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
adds(&str, (char*)b64.data);
|
|
Packit |
aea12f |
adds(&str, "\n");
|
|
Packit |
aea12f |
gnutls_free(b64.data);
|
|
Packit |
aea12f |
gnutls_free(data.data);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
count = gnutls_pkcs7_get_crl_count(pkcs7);
|
|
Packit |
aea12f |
if (count > 0) {
|
|
Packit |
aea12f |
addf(&str, "Number of CRLs: %u\n\n", count);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
for (i = 0; i < count; i++) {
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
gnutls_pkcs7_get_crl_raw2(pkcs7, i, &data);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
addf(&str,
|
|
Packit |
aea12f |
"Error: cannot print certificate %d\n",
|
|
Packit |
aea12f |
i);
|
|
Packit |
aea12f |
continue;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
gnutls_pem_base64_encode_alloc("X509 CRL",
|
|
Packit |
aea12f |
&data, &b64);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_free(data.data);
|
|
Packit |
aea12f |
continue;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
adds(&str, (char*)b64.data);
|
|
Packit |
aea12f |
adds(&str, "\n");
|
|
Packit |
aea12f |
gnutls_free(b64.data);
|
|
Packit |
aea12f |
gnutls_free(data.data);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return _gnutls_buffer_to_datum(&str, out, 1);
|
|
Packit |
aea12f |
}
|