Blame lib/x509/pkcs7-output.c

Packit Service 4684c1
/*
Packit Service 4684c1
 * Copyright (C) 2015 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
#include "gnutls_int.h"
Packit Service 4684c1
#include <common.h>
Packit Service 4684c1
#include <x509.h>
Packit Service 4684c1
#include <x509_int.h>
Packit Service 4684c1
#include <num.h>
Packit Service 4684c1
#include "errors.h"
Packit Service 4684c1
#include <extras/randomart.h>
Packit Service 4684c1
#include <pkcs7_int.h>
Packit Service 4684c1
Packit Service 4684c1
#define addf _gnutls_buffer_append_printf
Packit Service 4684c1
#define adds _gnutls_buffer_append_str
Packit Service 4684c1
Packit Service 4684c1
static void print_dn(gnutls_buffer_st * str, const char *prefix,
Packit Service 4684c1
		     const gnutls_datum_t * raw)
Packit Service 4684c1
{
Packit Service 4684c1
	gnutls_x509_dn_t dn = NULL;
Packit Service 4684c1
	gnutls_datum_t output = { NULL, 0 };
Packit Service 4684c1
	int ret;
Packit Service 4684c1
Packit Service 4684c1
	ret = gnutls_x509_dn_init(&dn;;
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		addf(str, "%s: [error]\n", prefix);
Packit Service 4684c1
		return;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	ret = gnutls_x509_dn_import(dn, raw);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		addf(str, "%s: [error]\n", prefix);
Packit Service 4684c1
		goto cleanup;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	ret = gnutls_x509_dn_get_str2(dn, &output, 0);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		addf(str, "%s: [error]\n", prefix);
Packit Service 4684c1
		goto cleanup;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	addf(str, "%s: %s\n", prefix, output.data);
Packit Service 4684c1
Packit Service 4684c1
 cleanup:
Packit Service 4684c1
	gnutls_x509_dn_deinit(dn);
Packit Service 4684c1
	gnutls_free(output.data);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* Do not encode ASN1 and type for now */
Packit Service 4684c1
#define ENTRY(oid, name, type) {oid, sizeof(oid)-1, name, sizeof(name)-1, NULL, type}
Packit Service 4684c1
#define ENTRY2(oid, name) {oid, sizeof(oid)-1, name, sizeof(name)-1, NULL, ASN1_ETYPE_INVALID}
Packit Service 4684c1
Packit Service 4684c1
static const struct oid_to_string pkcs7_attrs[] = {
Packit Service 4684c1
	ENTRY ("1.2.840.113549.1.9.3", "contentType", ASN1_ETYPE_OBJECT_ID),
Packit Service 4684c1
	ENTRY ("1.2.840.113549.1.9.4", "messageDigest", ASN1_ETYPE_OCTET_STRING),
Packit Service 4684c1
	ENTRY ("1.2.840.113549.1.9.5", "signingTime", ASN1_ETYPE_INVALID),
Packit Service 4684c1
	ENTRY2("1.2.840.113549.1.9.6", "countersignature"),
Packit Service 4684c1
	ENTRY2("1.2.840.113549.1.9.15", "smimeCapabilities"),
Packit Service 4684c1
Packit Service 4684c1
	ENTRY2("1.2.840.113549.1.9.16.2.1", "aa-receiptRequest"),
Packit Service 4684c1
	ENTRY2("1.2.840.113549.1.9.16.2.2", "aa-securityLabel"),
Packit Service 4684c1
	ENTRY2("1.2.840.113549.1.9.16.2.3", "aa-mlExpandHistory"),
Packit Service 4684c1
	ENTRY2("1.2.840.113549.1.9.16.2.4", "aa-contentHint"),
Packit Service 4684c1
	ENTRY2("1.2.840.113549.1.9.16.2.9", "aa-equivalentLabels"),
Packit Service 4684c1
	ENTRY2("1.2.840.113549.1.9.16.2.10", "aa-contentReference"),
Packit Service 4684c1
	ENTRY2("1.2.840.113549.1.9.16.2.11", "aa-encrypKeyPref"),
Packit Service 4684c1
	ENTRY2("1.2.840.113549.1.9.16.2.12", "aa-signingCertificate"),
Packit Service 4684c1
	ENTRY2("1.2.840.113549.1.9.16.2.19", "aa-ets-otherSigCert"),
Packit Service 4684c1
	ENTRY2("1.2.840.113549.1.9.16.2.47", "aa-signingCertificateV2"),
Packit Service 4684c1
Packit Service 4684c1
	{NULL, 0, NULL, 0, NULL, 0}
Packit Service 4684c1
};
Packit Service 4684c1
Packit Service 4684c1
static void print_raw(gnutls_buffer_st * str, const char *prefix,
Packit Service 4684c1
		      const gnutls_datum_t * raw)
Packit Service 4684c1
{
Packit Service 4684c1
	gnutls_datum_t result;
Packit Service 4684c1
	int ret;
Packit Service 4684c1
Packit Service 4684c1
	if (raw->data == NULL || raw->size == 0)
Packit Service 4684c1
		return;
Packit Service 4684c1
Packit Service 4684c1
	ret = gnutls_hex_encode2(raw, &result);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		addf(str, "%s: [error]\n", prefix);
Packit Service 4684c1
		return;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	addf(str, "%s: %s\n", prefix, result.data);
Packit Service 4684c1
	gnutls_free(result.data);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
static void print_pkcs7_info(gnutls_pkcs7_signature_info_st * info,
Packit Service 4684c1
			     gnutls_buffer_st * str,
Packit Service 4684c1
			     gnutls_certificate_print_formats_t format)
Packit Service 4684c1
{
Packit Service 4684c1
	unsigned i;
Packit Service 4684c1
	char *oid;
Packit Service 4684c1
	gnutls_datum_t data;
Packit Service 4684c1
	char prefix[128];
Packit Service 4684c1
	char s[42];
Packit Service 4684c1
	size_t max;
Packit Service 4684c1
	int ret;
Packit Service 4684c1
	const struct oid_to_string * entry;
Packit Service 4684c1
Packit Service 4684c1
	if (info->issuer_dn.size > 0)
Packit Service 4684c1
		print_dn(str, "\tSigner's issuer DN", &info->issuer_dn);
Packit Service 4684c1
	print_raw(str, "\tSigner's serial", &info->signer_serial);
Packit Service 4684c1
	print_raw(str, "\tSigner's issuer key ID", &info->issuer_keyid);
Packit Service 4684c1
	if (info->signing_time != -1) {
Packit Service 4684c1
		struct tm t;
Packit Service 4684c1
		if (gmtime_r(&info->signing_time, &t) == NULL) {
Packit Service 4684c1
			addf(str, "error: gmtime_r (%ld)\n",
Packit Service 4684c1
			     (unsigned long)info->signing_time);
Packit Service 4684c1
		} else {
Packit Service 4684c1
			max = sizeof(s);
Packit Service 4684c1
			if (strftime(s, max, "%a %b %d %H:%M:%S UTC %Y", &t) ==
Packit Service 4684c1
			    0) {
Packit Service 4684c1
				addf(str, "error: strftime (%ld)\n",
Packit Service 4684c1
				     (unsigned long)info->signing_time);
Packit Service 4684c1
			} else {
Packit Service 4684c1
				addf(str, "\tSigning time: %s\n", s);
Packit Service 4684c1
			}
Packit Service 4684c1
		}
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	addf(str, "\tSignature Algorithm: %s\n",
Packit Service 4684c1
	     gnutls_sign_get_name(info->algo));
Packit Service 4684c1
Packit Service 4684c1
	if (format == GNUTLS_CRT_PRINT_FULL) {
Packit Service 4684c1
		if (info->signed_attrs) {
Packit Service 4684c1
			for (i = 0;; i++) {
Packit Service 4684c1
				ret =
Packit Service 4684c1
				    gnutls_pkcs7_get_attr(info->signed_attrs, i,
Packit Service 4684c1
							  &oid, &data, 0);
Packit Service 4684c1
				if (ret < 0)
Packit Service 4684c1
					break;
Packit Service 4684c1
				if (i == 0)
Packit Service 4684c1
					addf(str, "\tSigned Attributes:\n");
Packit Service 4684c1
Packit Service 4684c1
				entry = _gnutls_oid_get_entry(pkcs7_attrs, oid);
Packit Service 4684c1
				snprintf(prefix, sizeof(prefix), "\t\t%s",
Packit Service 4684c1
						(entry && entry->name_desc) ? entry->name_desc : oid);
Packit Service 4684c1
				print_raw(str, prefix, &data);
Packit Service 4684c1
				gnutls_free(data.data);
Packit Service 4684c1
			}
Packit Service 4684c1
		}
Packit Service 4684c1
		if (info->unsigned_attrs) {
Packit Service 4684c1
			for (i = 0;; i++) {
Packit Service 4684c1
				ret =
Packit Service 4684c1
				    gnutls_pkcs7_get_attr(info->unsigned_attrs,
Packit Service 4684c1
							  i, &oid, &data, 0);
Packit Service 4684c1
				if (ret < 0)
Packit Service 4684c1
					break;
Packit Service 4684c1
				if (i == 0)
Packit Service 4684c1
					addf(str, "\tUnsigned Attributes:\n");
Packit Service 4684c1
Packit Service 4684c1
				entry = _gnutls_oid_get_entry(pkcs7_attrs, oid);
Packit Service 4684c1
				snprintf(prefix, sizeof(prefix), "\t\t%s",
Packit Service 4684c1
						(entry && entry->name_desc) ? entry->name_desc : oid);
Packit Service 4684c1
				print_raw(str, prefix, &data);
Packit Service 4684c1
				gnutls_free(data.data);
Packit Service 4684c1
			}
Packit Service 4684c1
		}
Packit Service 4684c1
	}
Packit Service 4684c1
	adds(str, "\n");
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_pkcs7_print_signature_info:
Packit Service 4684c1
 * @info: The PKCS7 signature info struct to be printed
Packit Service 4684c1
 * @format: Indicate the format to use
Packit Service 4684c1
 * @out: Newly allocated datum with null terminated string.
Packit Service 4684c1
 *
Packit Service 4684c1
 * This function will pretty print a PKCS #7 signature info structure, suitable
Packit Service 4684c1
 * for display to a human.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Currently the supported formats are %GNUTLS_CRT_PRINT_FULL and
Packit Service 4684c1
 * %GNUTLS_CRT_PRINT_COMPACT.
Packit Service 4684c1
 *
Packit Service 4684c1
 * The output @out needs to be deallocated using gnutls_free().
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.6.14
Packit Service 4684c1
 **/
Packit Service 4684c1
int gnutls_pkcs7_print_signature_info(gnutls_pkcs7_signature_info_st * info,
Packit Service 4684c1
				      gnutls_certificate_print_formats_t format,
Packit Service 4684c1
				      gnutls_datum_t * out)
Packit Service 4684c1
{
Packit Service 4684c1
	gnutls_buffer_st str;
Packit Service 4684c1
Packit Service 4684c1
	_gnutls_buffer_init(&str);
Packit Service 4684c1
	print_pkcs7_info(info, &str, format);
Packit Service 4684c1
Packit Service 4684c1
	return _gnutls_buffer_to_datum(&str, out, 1);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_pkcs7_crt_print:
Packit Service 4684c1
 * @pkcs7: The PKCS7 struct to be printed
Packit Service 4684c1
 * @format: Indicate the format to use
Packit Service 4684c1
 * @out: Newly allocated datum with null terminated string.
Packit Service 4684c1
 *
Packit Service 4684c1
 * This function will pretty print a signed PKCS #7 structure, suitable for
Packit Service 4684c1
 * display to a human.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Currently the supported formats are %GNUTLS_CRT_PRINT_FULL and
Packit Service 4684c1
 * %GNUTLS_CRT_PRINT_COMPACT.
Packit Service 4684c1
 *
Packit Service 4684c1
 * The output @out needs to be deallocated using gnutls_free().
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_pkcs7_print(gnutls_pkcs7_t pkcs7,
Packit Service 4684c1
		       gnutls_certificate_print_formats_t format,
Packit Service 4684c1
		       gnutls_datum_t * out)
Packit Service 4684c1
{
Packit Service 4684c1
	int count, ret, i;
Packit Service 4684c1
	gnutls_pkcs7_signature_info_st info;
Packit Service 4684c1
	gnutls_buffer_st str;
Packit Service 4684c1
	const char *oid;
Packit Service 4684c1
Packit Service 4684c1
	_gnutls_buffer_init(&str);
Packit Service 4684c1
Packit Service 4684c1
	/* For backwards compatibility with structures using the default OID,
Packit Service 4684c1
	 * we don't print the eContent Type explicitly */
Packit Service 4684c1
	oid = gnutls_pkcs7_get_embedded_data_oid(pkcs7);
Packit Service 4684c1
	if (oid) {
Packit Service 4684c1
		if (strcmp(oid, DATA_OID) != 0
Packit Service 4684c1
		    && strcmp(oid, DIGESTED_DATA_OID) != 0) {
Packit Service 4684c1
			addf(&str, "eContent Type: %s\n", oid);
Packit Service 4684c1
		}
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	for (i = 0;; i++) {
Packit Service 4684c1
		if (i == 0)
Packit Service 4684c1
			addf(&str, "Signers:\n");
Packit Service 4684c1
Packit Service 4684c1
		ret = gnutls_pkcs7_get_signature_info(pkcs7, i, &info;;
Packit Service 4684c1
		if (ret < 0)
Packit Service 4684c1
			break;
Packit Service 4684c1
Packit Service 4684c1
		print_pkcs7_info(&info, &str, format);
Packit Service 4684c1
		gnutls_pkcs7_signature_info_deinit(&info;;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	if (format == GNUTLS_CRT_PRINT_FULL) {
Packit Service 4684c1
		gnutls_datum_t data, b64;
Packit Service 4684c1
Packit Service 4684c1
		count = gnutls_pkcs7_get_crt_count(pkcs7);
Packit Service 4684c1
Packit Service 4684c1
		if (count > 0) {
Packit Service 4684c1
			addf(&str, "Number of certificates: %u\n\n",
Packit Service 4684c1
			     count);
Packit Service 4684c1
Packit Service 4684c1
			for (i = 0; i < count; i++) {
Packit Service 4684c1
				ret =
Packit Service 4684c1
				    gnutls_pkcs7_get_crt_raw2(pkcs7, i, &data);
Packit Service 4684c1
				if (ret < 0) {
Packit Service 4684c1
					addf(&str,
Packit Service 4684c1
					     "Error: cannot print certificate %d\n",
Packit Service 4684c1
					     i);
Packit Service 4684c1
					continue;
Packit Service 4684c1
				}
Packit Service 4684c1
Packit Service 4684c1
				ret =
Packit Service 4684c1
				    gnutls_pem_base64_encode_alloc
Packit Service 4684c1
				    ("CERTIFICATE", &data, &b64);
Packit Service 4684c1
				if (ret < 0) {
Packit Service 4684c1
					gnutls_free(data.data);
Packit Service 4684c1
					continue;
Packit Service 4684c1
				}
Packit Service 4684c1
Packit Service 4684c1
				adds(&str, (char*)b64.data);
Packit Service 4684c1
				adds(&str, "\n");
Packit Service 4684c1
				gnutls_free(b64.data);
Packit Service 4684c1
				gnutls_free(data.data);
Packit Service 4684c1
			}
Packit Service 4684c1
		}
Packit Service 4684c1
Packit Service 4684c1
		count = gnutls_pkcs7_get_crl_count(pkcs7);
Packit Service 4684c1
		if (count > 0) {
Packit Service 4684c1
			addf(&str, "Number of CRLs: %u\n\n", count);
Packit Service 4684c1
Packit Service 4684c1
			for (i = 0; i < count; i++) {
Packit Service 4684c1
				ret =
Packit Service 4684c1
				    gnutls_pkcs7_get_crl_raw2(pkcs7, i, &data);
Packit Service 4684c1
				if (ret < 0) {
Packit Service 4684c1
					addf(&str,
Packit Service 4684c1
					     "Error: cannot print certificate %d\n",
Packit Service 4684c1
					     i);
Packit Service 4684c1
					continue;
Packit Service 4684c1
				}
Packit Service 4684c1
Packit Service 4684c1
				ret =
Packit Service 4684c1
				    gnutls_pem_base64_encode_alloc("X509 CRL",
Packit Service 4684c1
								   &data, &b64);
Packit Service 4684c1
				if (ret < 0) {
Packit Service 4684c1
					gnutls_free(data.data);
Packit Service 4684c1
					continue;
Packit Service 4684c1
				}
Packit Service 4684c1
Packit Service 4684c1
				adds(&str, (char*)b64.data);
Packit Service 4684c1
				adds(&str, "\n");
Packit Service 4684c1
				gnutls_free(b64.data);
Packit Service 4684c1
				gnutls_free(data.data);
Packit Service 4684c1
			}
Packit Service 4684c1
		}
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	return _gnutls_buffer_to_datum(&str, out, 1);
Packit Service 4684c1
}