|
Packit Service |
3749ba |
/*
|
|
Packit Service |
3749ba |
* Copyright (C) 2012 Red Hat Inc.
|
|
Packit Service |
3749ba |
*
|
|
Packit Service |
3749ba |
* Redistribution and use in source and binary forms, with or without
|
|
Packit Service |
3749ba |
* modification, are permitted provided that the following conditions
|
|
Packit Service |
3749ba |
* are met:
|
|
Packit Service |
3749ba |
*
|
|
Packit Service |
3749ba |
* * Redistributions of source code must retain the above
|
|
Packit Service |
3749ba |
* copyright notice, this list of conditions and the
|
|
Packit Service |
3749ba |
* following disclaimer.
|
|
Packit Service |
3749ba |
* * Redistributions in binary form must reproduce the
|
|
Packit Service |
3749ba |
* above copyright notice, this list of conditions and
|
|
Packit Service |
3749ba |
* the following disclaimer in the documentation and/or
|
|
Packit Service |
3749ba |
* other materials provided with the distribution.
|
|
Packit Service |
3749ba |
* * The names of contributors to this software may not be
|
|
Packit Service |
3749ba |
* used to endorse or promote products derived from this
|
|
Packit Service |
3749ba |
* software without specific prior written permission.
|
|
Packit Service |
3749ba |
*
|
|
Packit Service |
3749ba |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
Packit Service |
3749ba |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
Packit Service |
3749ba |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
Packit Service |
3749ba |
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
Packit Service |
3749ba |
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
Packit Service |
3749ba |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
Packit Service |
3749ba |
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
|
Packit Service |
3749ba |
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
Packit Service |
3749ba |
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
Packit Service |
3749ba |
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
|
Packit Service |
3749ba |
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
Packit Service |
3749ba |
* DAMAGE.
|
|
Packit Service |
3749ba |
*
|
|
Packit Service |
3749ba |
* Author: Stef Walter <stefw@redhat.com>
|
|
Packit Service |
3749ba |
*/
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
#include "config.h"
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
#include "array.h"
|
|
Packit Service |
3749ba |
#include "asn1.h"
|
|
Packit Service |
3749ba |
#include "attrs.h"
|
|
Packit Service |
3749ba |
#define P11_DEBUG_FLAG P11_DEBUG_TRUST
|
|
Packit Service |
3749ba |
#include "debug.h"
|
|
Packit Service |
3749ba |
#include "dict.h"
|
|
Packit Service |
3749ba |
#include "digest.h"
|
|
Packit Service |
3749ba |
#include "message.h"
|
|
Packit Service |
3749ba |
#include "module.h"
|
|
Packit Service |
3749ba |
#include "oid.h"
|
|
Packit Service |
3749ba |
#include "parser.h"
|
|
Packit Service |
3749ba |
#include "path.h"
|
|
Packit Service |
3749ba |
#include "pem.h"
|
|
Packit Service |
3749ba |
#include "pkcs11x.h"
|
|
Packit Service |
3749ba |
#include "persist.h"
|
|
Packit Service |
3749ba |
#include "types.h"
|
|
Packit Service |
3749ba |
#include "x509.h"
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
#include <libtasn1.h>
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
#include <sys/types.h>
|
|
Packit Service |
3749ba |
#include <sys/stat.h>
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
#include <assert.h>
|
|
Packit Service |
3749ba |
#include <errno.h>
|
|
Packit Service |
3749ba |
#include <fcntl.h>
|
|
Packit Service |
3749ba |
#include <stdarg.h>
|
|
Packit Service |
3749ba |
#include <stdlib.h>
|
|
Packit Service |
3749ba |
#include <string.h>
|
|
Packit Service |
3749ba |
#include <unistd.h>
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
struct _p11_parser {
|
|
Packit Service |
3749ba |
p11_asn1_cache *asn1_cache;
|
|
Packit Service |
3749ba |
p11_dict *asn1_defs;
|
|
Packit Service |
3749ba |
bool asn1_owned;
|
|
Packit Service |
3749ba |
p11_persist *persist;
|
|
Packit Service |
3749ba |
char *basename;
|
|
Packit Service |
3749ba |
p11_array *parsed;
|
|
Packit Service |
3749ba |
p11_array *formats;
|
|
Packit Service |
3749ba |
int flags;
|
|
Packit Service |
3749ba |
};
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
#define ID_LENGTH P11_DIGEST_SHA1_LEN
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
typedef int (* parser_func) (p11_parser *parser,
|
|
Packit Service |
3749ba |
const unsigned char *data,
|
|
Packit Service |
3749ba |
size_t length);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
static CK_ATTRIBUTE *
|
|
Packit Service |
3749ba |
populate_trust (p11_parser *parser,
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE *attrs)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
CK_BBOOL trustedv;
|
|
Packit Service |
3749ba |
CK_BBOOL distrustv;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE trusted = { CKA_TRUSTED, &trustedv, sizeof (trustedv) };
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE distrust = { CKA_X_DISTRUSTED, &distrustv, sizeof (distrustv) };
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/*
|
|
Packit Service |
3749ba |
* If we're are parsing an anchor location, then warn about any ditsrusted
|
|
Packit Service |
3749ba |
* certificates there, but don't go ahead and automatically make them
|
|
Packit Service |
3749ba |
* trusted anchors.
|
|
Packit Service |
3749ba |
*/
|
|
Packit Service |
3749ba |
if (parser->flags & P11_PARSE_FLAG_ANCHOR) {
|
|
Packit Service |
3749ba |
if (p11_attrs_find_bool (attrs, CKA_X_DISTRUSTED, &distrustv) && distrustv) {
|
|
Packit Service |
3749ba |
p11_message ("certificate with distrust in location for anchors: %s", parser->basename);
|
|
Packit Service |
3749ba |
return attrs;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
trustedv = CK_TRUE;
|
|
Packit Service |
3749ba |
distrustv = CK_FALSE;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/*
|
|
Packit Service |
3749ba |
* If we're parsing a blacklist location, then force all certificates to
|
|
Packit Service |
3749ba |
* be blacklisted, regardless of whether they contain anchor information.
|
|
Packit Service |
3749ba |
*/
|
|
Packit Service |
3749ba |
} else if (parser->flags & P11_PARSE_FLAG_BLACKLIST) {
|
|
Packit Service |
3749ba |
if (p11_attrs_find_bool (attrs, CKA_TRUSTED, &trustedv) && trustedv)
|
|
Packit Service |
3749ba |
p11_message ("overriding trust for anchor in blacklist: %s", parser->basename);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
trustedv = CK_FALSE;
|
|
Packit Service |
3749ba |
distrustv = CK_TRUE;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/*
|
|
Packit Service |
3749ba |
* If the location doesn't have a flag, then fill in trust attributes
|
|
Packit Service |
3749ba |
* if they are missing: neither an anchor or blacklist.
|
|
Packit Service |
3749ba |
*/
|
|
Packit Service |
3749ba |
} else {
|
|
Packit Service |
3749ba |
trustedv = CK_FALSE;
|
|
Packit Service |
3749ba |
distrustv = CK_FALSE;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
if (p11_attrs_find_valid (attrs, CKA_TRUSTED))
|
|
Packit Service |
3749ba |
trusted.type = CKA_INVALID;
|
|
Packit Service |
3749ba |
if (p11_attrs_find_valid (attrs, CKA_X_DISTRUSTED))
|
|
Packit Service |
3749ba |
distrust.type = CKA_INVALID;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
return p11_attrs_build (attrs, &trusted, &distrust, NULL);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
static void
|
|
Packit Service |
3749ba |
sink_object (p11_parser *parser,
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE *attrs)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
CK_OBJECT_CLASS klass;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
if (p11_attrs_find_ulong (attrs, CKA_CLASS, &klass) &&
|
|
Packit Service |
3749ba |
klass == CKO_CERTIFICATE) {
|
|
Packit Service |
3749ba |
attrs = populate_trust (parser, attrs);
|
|
Packit Service |
3749ba |
return_if_fail (attrs != NULL);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
if (!p11_array_push (parser->parsed, attrs))
|
|
Packit Service |
3749ba |
return_if_reached ();
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
static CK_ATTRIBUTE *
|
|
Packit Service |
3749ba |
certificate_attrs (p11_parser *parser,
|
|
Packit Service |
3749ba |
const unsigned char *der,
|
|
Packit Service |
3749ba |
size_t der_len)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
CK_OBJECT_CLASS klassv = CKO_CERTIFICATE;
|
|
Packit Service |
3749ba |
CK_CERTIFICATE_TYPE x509 = CKC_X_509;
|
|
Packit Service |
3749ba |
CK_BBOOL modifiablev = CK_FALSE;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &modifiablev, sizeof (modifiablev) };
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE klass = { CKA_CLASS, &klassv, sizeof (klassv) };
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE certificate_type = { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) };
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE value = { CKA_VALUE, (void *)der, der_len };
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
return p11_attrs_build (NULL, &klass, &modifiable, &certificate_type, &value, NULL);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
int
|
|
Packit Service |
3749ba |
p11_parser_format_x509 (p11_parser *parser,
|
|
Packit Service |
3749ba |
const unsigned char *data,
|
|
Packit Service |
3749ba |
size_t length)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
char message[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE *attrs;
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE *value;
|
|
Packit Service |
3749ba |
node_asn *cert;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
cert = p11_asn1_decode (parser->asn1_defs, "PKIX1.Certificate", data, length, message);
|
|
Packit Service |
3749ba |
if (cert == NULL)
|
|
Packit Service |
3749ba |
return P11_PARSE_UNRECOGNIZED;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
attrs = certificate_attrs (parser, data, length);
|
|
Packit Service |
3749ba |
return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
value = p11_attrs_find_valid (attrs, CKA_VALUE);
|
|
Packit Service |
3749ba |
return_val_if_fail (value != NULL, P11_PARSE_FAILURE);
|
|
Packit Service |
3749ba |
p11_asn1_cache_take (parser->asn1_cache, cert, "PKIX1.Certificate",
|
|
Packit Service |
3749ba |
value->pValue, value->ulValueLen);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
sink_object (parser, attrs);
|
|
Packit Service |
3749ba |
return P11_PARSE_SUCCESS;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
static CK_ATTRIBUTE *
|
|
Packit Service |
3749ba |
extension_attrs (p11_parser *parser,
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE *public_key_info,
|
|
Packit Service |
3749ba |
const char *oid_str,
|
|
Packit Service |
3749ba |
const unsigned char *oid_der,
|
|
Packit Service |
3749ba |
bool critical,
|
|
Packit Service |
3749ba |
const unsigned char *value,
|
|
Packit Service |
3749ba |
int length)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
CK_OBJECT_CLASS klassv = CKO_X_CERTIFICATE_EXTENSION;
|
|
Packit Service |
3749ba |
CK_BBOOL modifiablev = CK_FALSE;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE klass = { CKA_CLASS, &klassv, sizeof (klassv) };
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &modifiablev, sizeof (modifiablev) };
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE oid = { CKA_OBJECT_ID, (void *)oid_der, p11_oid_length (oid_der) };
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE *attrs;
|
|
Packit Service |
3749ba |
node_asn *dest;
|
|
Packit Service |
3749ba |
unsigned char *der;
|
|
Packit Service |
3749ba |
size_t len;
|
|
Packit Service |
3749ba |
int ret;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
attrs = p11_attrs_build (NULL, public_key_info, &klass, &modifiable, &oid, NULL);
|
|
Packit Service |
3749ba |
return_val_if_fail (attrs != NULL, NULL);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
dest = p11_asn1_create (parser->asn1_defs, "PKIX1.Extension");
|
|
Packit Service |
3749ba |
return_val_if_fail (dest != NULL, NULL);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
ret = asn1_write_value (dest, "extnID", oid_str, 1);
|
|
Packit Service |
3749ba |
return_val_if_fail (ret == ASN1_SUCCESS, NULL);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
if (critical)
|
|
Packit Service |
3749ba |
ret = asn1_write_value (dest, "critical", "TRUE", 1);
|
|
Packit Service |
3749ba |
return_val_if_fail (ret == ASN1_SUCCESS, NULL);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
ret = asn1_write_value (dest, "extnValue", value, length);
|
|
Packit Service |
3749ba |
return_val_if_fail (ret == ASN1_SUCCESS, NULL);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
der = p11_asn1_encode (dest, &len;;
|
|
Packit Service |
3749ba |
return_val_if_fail (der != NULL, NULL);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
attrs = p11_attrs_take (attrs, CKA_VALUE, der, len);
|
|
Packit Service |
3749ba |
return_val_if_fail (attrs != NULL, NULL);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* An opmitization so that the builder can get at this without parsing */
|
|
Packit Service |
3749ba |
p11_asn1_cache_take (parser->asn1_cache, dest, "PKIX1.Extension", der, len);
|
|
Packit Service |
3749ba |
return attrs;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
static CK_ATTRIBUTE *
|
|
Packit Service |
3749ba |
attached_attrs (p11_parser *parser,
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE *public_key_info,
|
|
Packit Service |
3749ba |
const char *oid_str,
|
|
Packit Service |
3749ba |
const unsigned char *oid_der,
|
|
Packit Service |
3749ba |
bool critical,
|
|
Packit Service |
3749ba |
node_asn *ext)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE *attrs;
|
|
Packit Service |
3749ba |
unsigned char *der;
|
|
Packit Service |
3749ba |
size_t len;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
der = p11_asn1_encode (ext, &len;;
|
|
Packit Service |
3749ba |
return_val_if_fail (der != NULL, NULL);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
attrs = extension_attrs (parser, public_key_info, oid_str, oid_der,
|
|
Packit Service |
3749ba |
critical, der, len);
|
|
Packit Service |
3749ba |
return_val_if_fail (attrs != NULL, NULL);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
free (der);
|
|
Packit Service |
3749ba |
return attrs;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
static p11_dict *
|
|
Packit Service |
3749ba |
load_seq_of_oid_str (node_asn *node,
|
|
Packit Service |
3749ba |
const char *seqof)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
p11_dict *oids;
|
|
Packit Service |
3749ba |
char field[128];
|
|
Packit Service |
3749ba |
char *oid;
|
|
Packit Service |
3749ba |
size_t len;
|
|
Packit Service |
3749ba |
int i;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
oids = p11_dict_new (p11_dict_str_hash, p11_dict_str_equal, free, NULL);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
for (i = 1; ; i++) {
|
|
Packit Service |
3749ba |
if (snprintf (field, sizeof (field), "%s.?%u", seqof, i) < 0)
|
|
Packit Service |
3749ba |
return_val_if_reached (NULL);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
oid = p11_asn1_read (node, field, &len;;
|
|
Packit Service |
3749ba |
if (oid == NULL)
|
|
Packit Service |
3749ba |
break;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
if (!p11_dict_set (oids, oid, oid))
|
|
Packit Service |
3749ba |
return_val_if_reached (NULL);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
return oids;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
static CK_ATTRIBUTE *
|
|
Packit Service |
3749ba |
attached_eku_attrs (p11_parser *parser,
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE *public_key_info,
|
|
Packit Service |
3749ba |
const char *oid_str,
|
|
Packit Service |
3749ba |
const unsigned char *oid_der,
|
|
Packit Service |
3749ba |
bool critical,
|
|
Packit Service |
3749ba |
p11_dict *oid_strs)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE *attrs;
|
|
Packit Service |
3749ba |
p11_dictiter iter;
|
|
Packit Service |
3749ba |
node_asn *dest;
|
|
Packit Service |
3749ba |
int count = 0;
|
|
Packit Service |
3749ba |
void *value;
|
|
Packit Service |
3749ba |
int ret;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
dest = p11_asn1_create (parser->asn1_defs, "PKIX1.ExtKeyUsageSyntax");
|
|
Packit Service |
3749ba |
return_val_if_fail (dest != NULL, NULL);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
p11_dict_iterate (oid_strs, &iter);
|
|
Packit Service |
3749ba |
while (p11_dict_next (&iter, NULL, &value)) {
|
|
Packit Service |
3749ba |
ret = asn1_write_value (dest, "", "NEW", 1);
|
|
Packit Service |
3749ba |
return_val_if_fail (ret == ASN1_SUCCESS, NULL);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
ret = asn1_write_value (dest, "?LAST", value, -1);
|
|
Packit Service |
3749ba |
return_val_if_fail (ret == ASN1_SUCCESS, NULL);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
count++;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/*
|
|
Packit Service |
3749ba |
* If no oids have been written, then we have to put in a reserved
|
|
Packit Service |
3749ba |
* value, due to the way that ExtendedKeyUsage is defined in RFC 5280.
|
|
Packit Service |
3749ba |
* There must be at least one purpose. This is important since *not*
|
|
Packit Service |
3749ba |
* having an ExtendedKeyUsage is very different than having one without
|
|
Packit Service |
3749ba |
* certain usages.
|
|
Packit Service |
3749ba |
*
|
|
Packit Service |
3749ba |
* We account for this in p11_parse_extended_key_usage(). However for
|
|
Packit Service |
3749ba |
* most callers this should not matter, as they only check whether a
|
|
Packit Service |
3749ba |
* given purpose is present, and don't make assumptions about ones
|
|
Packit Service |
3749ba |
* that they don't know about.
|
|
Packit Service |
3749ba |
*/
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
if (count == 0) {
|
|
Packit Service |
3749ba |
ret = asn1_write_value (dest, "", "NEW", 1);
|
|
Packit Service |
3749ba |
return_val_if_fail (ret == ASN1_SUCCESS, NULL);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
ret = asn1_write_value (dest, "?LAST", P11_OID_RESERVED_PURPOSE_STR, -1);
|
|
Packit Service |
3749ba |
return_val_if_fail (ret == ASN1_SUCCESS, NULL);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
attrs = attached_attrs (parser, public_key_info, oid_str, oid_der, critical, dest);
|
|
Packit Service |
3749ba |
asn1_delete_structure (&dest);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
return attrs;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
static CK_ATTRIBUTE *
|
|
Packit Service |
3749ba |
build_openssl_extensions (p11_parser *parser,
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE *cert,
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE *public_key_info,
|
|
Packit Service |
3749ba |
node_asn *aux,
|
|
Packit Service |
3749ba |
const unsigned char *aux_der,
|
|
Packit Service |
3749ba |
size_t aux_len)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
CK_BBOOL trusted = CK_FALSE;
|
|
Packit Service |
3749ba |
CK_BBOOL distrust = CK_FALSE;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE trust_attrs[] = {
|
|
Packit Service |
3749ba |
{ CKA_TRUSTED, &trusted, sizeof (trusted) },
|
|
Packit Service |
3749ba |
{ CKA_X_DISTRUSTED, &distrust, sizeof (distrust) },
|
|
Packit Service |
3749ba |
{ CKA_INVALID },
|
|
Packit Service |
3749ba |
};
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE *attrs;
|
|
Packit Service |
3749ba |
p11_dict *trust = NULL;
|
|
Packit Service |
3749ba |
p11_dict *reject = NULL;
|
|
Packit Service |
3749ba |
p11_dictiter iter;
|
|
Packit Service |
3749ba |
void *key;
|
|
Packit Service |
3749ba |
int start;
|
|
Packit Service |
3749ba |
int end;
|
|
Packit Service |
3749ba |
int ret;
|
|
Packit Service |
3749ba |
int num;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/*
|
|
Packit Service |
3749ba |
* This will load an empty list if there is no OPTIONAL trust field.
|
|
Packit Service |
3749ba |
* OpenSSL assumes that for a TRUSTED CERTIFICATE a missing trust field
|
|
Packit Service |
3749ba |
* is identical to untrusted for all purposes.
|
|
Packit Service |
3749ba |
*
|
|
Packit Service |
3749ba |
* This is different from ExtendedKeyUsage, where a missing certificate
|
|
Packit Service |
3749ba |
* extension means that it is trusted for all purposes.
|
|
Packit Service |
3749ba |
*/
|
|
Packit Service |
3749ba |
trust = load_seq_of_oid_str (aux, "trust");
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
ret = asn1_number_of_elements (aux, "reject", &num);
|
|
Packit Service |
3749ba |
return_val_if_fail (ret == ASN1_SUCCESS || ret == ASN1_ELEMENT_NOT_FOUND, NULL);
|
|
Packit Service |
3749ba |
if (ret == ASN1_SUCCESS)
|
|
Packit Service |
3749ba |
reject = load_seq_of_oid_str (aux, "reject");
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* Remove all rejected oids from the trust set */
|
|
Packit Service |
3749ba |
if (trust && reject) {
|
|
Packit Service |
3749ba |
p11_dict_iterate (reject, &iter);
|
|
Packit Service |
3749ba |
while (p11_dict_next (&iter, &key, NULL))
|
|
Packit Service |
3749ba |
p11_dict_remove (trust, key);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/*
|
|
Packit Service |
3749ba |
* The trust field (or lack of it) becomes a standard ExtKeyUsageSyntax.
|
|
Packit Service |
3749ba |
*
|
|
Packit Service |
3749ba |
* critical: require that this is enforced
|
|
Packit Service |
3749ba |
*/
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
if (trust) {
|
|
Packit Service |
3749ba |
attrs = attached_eku_attrs (parser, public_key_info,
|
|
Packit Service |
3749ba |
P11_OID_EXTENDED_KEY_USAGE_STR,
|
|
Packit Service |
3749ba |
P11_OID_EXTENDED_KEY_USAGE,
|
|
Packit Service |
3749ba |
true, trust);
|
|
Packit Service |
3749ba |
return_val_if_fail (attrs != NULL, NULL);
|
|
Packit Service |
3749ba |
sink_object (parser, attrs);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/*
|
|
Packit Service |
3749ba |
* For the reject field we use a custom defined extension. We track this
|
|
Packit Service |
3749ba |
* for completeness, although the above ExtendedKeyUsage extension handles
|
|
Packit Service |
3749ba |
* this data fine. See oid.h for more details. It uses ExtKeyUsageSyntax structure.
|
|
Packit Service |
3749ba |
*
|
|
Packit Service |
3749ba |
* non-critical: non-standard, and also covered by trusts
|
|
Packit Service |
3749ba |
*/
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
if (reject && p11_dict_size (reject) > 0) {
|
|
Packit Service |
3749ba |
attrs = attached_eku_attrs (parser, public_key_info,
|
|
Packit Service |
3749ba |
P11_OID_OPENSSL_REJECT_STR,
|
|
Packit Service |
3749ba |
P11_OID_OPENSSL_REJECT,
|
|
Packit Service |
3749ba |
false, reject);
|
|
Packit Service |
3749ba |
return_val_if_fail (attrs != NULL, NULL);
|
|
Packit Service |
3749ba |
sink_object (parser, attrs);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/*
|
|
Packit Service |
3749ba |
* OpenSSL model blacklists as anchors with all purposes being removed/rejected,
|
|
Packit Service |
3749ba |
* we account for that here. If there is an ExtendedKeyUsage without any
|
|
Packit Service |
3749ba |
* useful purposes, then treat like a blacklist.
|
|
Packit Service |
3749ba |
*/
|
|
Packit Service |
3749ba |
if (trust && p11_dict_size (trust) == 0) {
|
|
Packit Service |
3749ba |
trusted = CK_FALSE;
|
|
Packit Service |
3749ba |
distrust = CK_TRUE;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/*
|
|
Packit Service |
3749ba |
* Otherwise a 'TRUSTED CERTIFICATE' in an input directory is enough to
|
|
Packit Service |
3749ba |
* mark this as a trusted certificate.
|
|
Packit Service |
3749ba |
*/
|
|
Packit Service |
3749ba |
} else if (trust && p11_dict_size (trust) > 0) {
|
|
Packit Service |
3749ba |
trusted = CK_TRUE;
|
|
Packit Service |
3749ba |
distrust = CK_FALSE;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/*
|
|
Packit Service |
3749ba |
* OpenSSL model blacklists as anchors with all purposes being removed/rejected,
|
|
Packit Service |
3749ba |
* we account for that here. If there is an ExtendedKeyUsage without any
|
|
Packit Service |
3749ba |
* useful purposes, then treat like a blacklist.
|
|
Packit Service |
3749ba |
*/
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
cert = p11_attrs_merge (cert, p11_attrs_dup (trust_attrs), true);
|
|
Packit Service |
3749ba |
return_val_if_fail (cert != NULL, NULL);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
p11_dict_free (trust);
|
|
Packit Service |
3749ba |
p11_dict_free (reject);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/*
|
|
Packit Service |
3749ba |
* For the keyid field we use the SubjectKeyIdentifier extension. It
|
|
Packit Service |
3749ba |
* is already in the correct form, an OCTET STRING.
|
|
Packit Service |
3749ba |
*
|
|
Packit Service |
3749ba |
* non-critical: as recommended in RFC 5280
|
|
Packit Service |
3749ba |
*/
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
ret = asn1_der_decoding_startEnd (aux, aux_der, aux_len, "keyid", &start, &end;;
|
|
Packit Service |
3749ba |
return_val_if_fail (ret == ASN1_SUCCESS || ret == ASN1_ELEMENT_NOT_FOUND, NULL);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
if (ret == ASN1_SUCCESS) {
|
|
Packit Service |
3749ba |
attrs = extension_attrs (parser, public_key_info,
|
|
Packit Service |
3749ba |
P11_OID_SUBJECT_KEY_IDENTIFIER_STR,
|
|
Packit Service |
3749ba |
P11_OID_SUBJECT_KEY_IDENTIFIER,
|
|
Packit Service |
3749ba |
false, aux_der + start, (end - start) + 1);
|
|
Packit Service |
3749ba |
return_val_if_fail (attrs != NULL, NULL);
|
|
Packit Service |
3749ba |
sink_object (parser, attrs);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
return cert;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
static int
|
|
Packit Service |
3749ba |
parse_openssl_trusted_certificate (p11_parser *parser,
|
|
Packit Service |
3749ba |
const unsigned char *data,
|
|
Packit Service |
3749ba |
size_t length)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
char message[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE *attrs;
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE public_key_info = { CKA_PUBLIC_KEY_INFO };
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE *value;
|
|
Packit Service |
3749ba |
char *label = NULL;
|
|
Packit Service |
3749ba |
node_asn *cert;
|
|
Packit Service |
3749ba |
node_asn *aux = NULL;
|
|
Packit Service |
3749ba |
ssize_t cert_len;
|
|
Packit Service |
3749ba |
size_t len;
|
|
Packit Service |
3749ba |
int start;
|
|
Packit Service |
3749ba |
int end;
|
|
Packit Service |
3749ba |
int ret;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/*
|
|
Packit Service |
3749ba |
* This OpenSSL format is weird. It's just two DER structures
|
|
Packit Service |
3749ba |
* placed end to end without any wrapping SEQ. So calculate the
|
|
Packit Service |
3749ba |
* length of the first DER TLV we see and try to parse that as
|
|
Packit Service |
3749ba |
* the X.509 certificate.
|
|
Packit Service |
3749ba |
*/
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
cert_len = p11_asn1_tlv_length (data, length);
|
|
Packit Service |
3749ba |
if (cert_len <= 0)
|
|
Packit Service |
3749ba |
return P11_PARSE_UNRECOGNIZED;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
cert = p11_asn1_decode (parser->asn1_defs, "PKIX1.Certificate", data, cert_len, message);
|
|
Packit Service |
3749ba |
if (cert == NULL)
|
|
Packit Service |
3749ba |
return P11_PARSE_UNRECOGNIZED;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* OpenSSL sometimes outputs TRUSTED CERTIFICATE format without the CertAux supplement */
|
|
Packit Service |
3749ba |
if (cert_len < length) {
|
|
Packit Service |
3749ba |
aux = p11_asn1_decode (parser->asn1_defs, "OPENSSL.CertAux", data + cert_len,
|
|
Packit Service |
3749ba |
length - cert_len, message);
|
|
Packit Service |
3749ba |
if (aux == NULL) {
|
|
Packit Service |
3749ba |
asn1_delete_structure (&cert);
|
|
Packit Service |
3749ba |
return P11_PARSE_UNRECOGNIZED;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
attrs = certificate_attrs (parser, data, cert_len);
|
|
Packit Service |
3749ba |
return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* Cache the parsed certificate ASN.1 for later use by the builder */
|
|
Packit Service |
3749ba |
value = p11_attrs_find_valid (attrs, CKA_VALUE);
|
|
Packit Service |
3749ba |
return_val_if_fail (value != NULL, P11_PARSE_FAILURE);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* Pull out the subject public key info */
|
|
Packit Service |
3749ba |
ret = asn1_der_decoding_startEnd (cert, data, cert_len,
|
|
Packit Service |
3749ba |
"tbsCertificate.subjectPublicKeyInfo", &start, &end;;
|
|
Packit Service |
3749ba |
return_val_if_fail (ret == ASN1_SUCCESS, P11_PARSE_FAILURE);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
public_key_info.pValue = (char *)data + start;
|
|
Packit Service |
3749ba |
public_key_info.ulValueLen = (end - start) + 1;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
p11_asn1_cache_take (parser->asn1_cache, cert, "PKIX1.Certificate",
|
|
Packit Service |
3749ba |
value->pValue, value->ulValueLen);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
/* Pull the label out of the CertAux */
|
|
Packit Service |
3749ba |
if (aux) {
|
|
Packit Service |
3749ba |
len = 0;
|
|
Packit Service |
3749ba |
label = p11_asn1_read (aux, "alias", &len;;
|
|
Packit Service |
3749ba |
if (label != NULL) {
|
|
Packit Service |
3749ba |
attrs = p11_attrs_take (attrs, CKA_LABEL, label, strlen (label));
|
|
Packit Service |
3749ba |
return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
attrs = build_openssl_extensions (parser, attrs, &public_key_info, aux,
|
|
Packit Service |
3749ba |
data + cert_len, length - cert_len);
|
|
Packit Service |
3749ba |
return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
sink_object (parser, attrs);
|
|
Packit Service |
3749ba |
asn1_delete_structure (&aux;;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
return P11_PARSE_SUCCESS;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
static void
|
|
Packit Service |
3749ba |
on_pem_block (const char *type,
|
|
Packit Service |
3749ba |
const unsigned char *contents,
|
|
Packit Service |
3749ba |
size_t length,
|
|
Packit Service |
3749ba |
void *user_data)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
p11_parser *parser = user_data;
|
|
Packit Service |
3749ba |
int ret;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
if (strcmp (type, "CERTIFICATE") == 0) {
|
|
Packit Service |
3749ba |
ret = p11_parser_format_x509 (parser, contents, length);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
} else if (strcmp (type, "TRUSTED CERTIFICATE") == 0) {
|
|
Packit Service |
3749ba |
ret = parse_openssl_trusted_certificate (parser, contents, length);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
} else {
|
|
Packit Service |
3749ba |
p11_debug ("Saw unsupported or unrecognized PEM block of type %s", type);
|
|
Packit Service |
3749ba |
ret = P11_PARSE_SUCCESS;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
if (ret != P11_PARSE_SUCCESS)
|
|
Packit Service |
3749ba |
p11_message ("Couldn't parse PEM block of type %s", type);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
int
|
|
Packit Service |
3749ba |
p11_parser_format_pem (p11_parser *parser,
|
|
Packit Service |
3749ba |
const unsigned char *data,
|
|
Packit Service |
3749ba |
size_t length)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
int num;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
num = p11_pem_parse ((const char *)data, length, on_pem_block, parser);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
if (num == 0)
|
|
Packit Service |
3749ba |
return P11_PARSE_UNRECOGNIZED;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
return P11_PARSE_SUCCESS;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
int
|
|
Packit Service |
3749ba |
p11_parser_format_persist (p11_parser *parser,
|
|
Packit Service |
3749ba |
const unsigned char *data,
|
|
Packit Service |
3749ba |
size_t length)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
CK_BBOOL modifiablev = CK_TRUE;
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE *attrs;
|
|
Packit Service |
3749ba |
p11_array *objects;
|
|
Packit Service |
3749ba |
bool ret;
|
|
Packit Service |
3749ba |
int i;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &modifiablev, sizeof (modifiablev) };
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
if (!p11_persist_magic (data, length))
|
|
Packit Service |
3749ba |
return P11_PARSE_UNRECOGNIZED;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
if (!parser->persist) {
|
|
Packit Service |
3749ba |
parser->persist = p11_persist_new ();
|
|
Packit Service |
3749ba |
return_val_if_fail (parser->persist != NULL, P11_PARSE_UNRECOGNIZED);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
objects = p11_array_new (NULL);
|
|
Packit Service |
3749ba |
return_val_if_fail (objects != NULL, P11_PARSE_FAILURE);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
ret = p11_persist_read (parser->persist, parser->basename, data, length, objects);
|
|
Packit Service |
3749ba |
if (ret) {
|
|
Packit Service |
3749ba |
if (!p11_persist_is_generated (data, length))
|
|
Packit Service |
3749ba |
modifiablev = CK_FALSE;
|
|
Packit Service |
3749ba |
for (i = 0; i < objects->num; i++) {
|
|
Packit Service |
3749ba |
attrs = p11_attrs_build (objects->elem[i], &modifiable, NULL);
|
|
Packit Service |
3749ba |
sink_object (parser, attrs);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
p11_array_free (objects);
|
|
Packit Service |
3749ba |
return ret ? P11_PARSE_SUCCESS : P11_PARSE_UNRECOGNIZED;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
p11_parser *
|
|
Packit Service |
3749ba |
p11_parser_new (p11_asn1_cache *asn1_cache)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
p11_parser parser = { 0, };
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
if (asn1_cache == NULL) {
|
|
Packit Service |
3749ba |
parser.asn1_owned = true;
|
|
Packit Service |
3749ba |
parser.asn1_defs = p11_asn1_defs_load ();
|
|
Packit Service |
3749ba |
} else {
|
|
Packit Service |
3749ba |
parser.asn1_defs = p11_asn1_cache_defs (asn1_cache);
|
|
Packit Service |
3749ba |
parser.asn1_cache = asn1_cache;
|
|
Packit Service |
3749ba |
parser.asn1_owned = false;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
parser.parsed = p11_array_new (p11_attrs_free);
|
|
Packit Service |
3749ba |
return_val_if_fail (parser.parsed != NULL, NULL);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
return memdup (&parser, sizeof (parser));
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
void
|
|
Packit Service |
3749ba |
p11_parser_free (p11_parser *parser)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
return_if_fail (parser != NULL);
|
|
Packit Service |
3749ba |
p11_persist_free (parser->persist);
|
|
Packit Service |
3749ba |
p11_array_free (parser->parsed);
|
|
Packit Service |
3749ba |
p11_array_free (parser->formats);
|
|
Packit Service |
3749ba |
if (parser->asn1_owned)
|
|
Packit Service |
3749ba |
p11_dict_free (parser->asn1_defs);
|
|
Packit Service |
3749ba |
free (parser);
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
p11_array *
|
|
Packit Service |
3749ba |
p11_parser_parsed (p11_parser *parser)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
return_val_if_fail (parser != NULL, NULL);
|
|
Packit Service |
3749ba |
return parser->parsed;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
void
|
|
Packit Service |
3749ba |
p11_parser_formats (p11_parser *parser,
|
|
Packit Service |
3749ba |
...)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
p11_array *formats;
|
|
Packit Service |
3749ba |
parser_func func;
|
|
Packit Service |
3749ba |
va_list va;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
formats = p11_array_new (NULL);
|
|
Packit Service |
3749ba |
return_if_fail (formats != NULL);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
va_start (va, parser);
|
|
Packit Service |
3749ba |
for (;;) {
|
|
Packit Service |
3749ba |
func = va_arg (va, parser_func);
|
|
Packit Service |
3749ba |
if (func == NULL)
|
|
Packit Service |
3749ba |
break;
|
|
Packit Service |
3749ba |
if (!p11_array_push (formats, func)) {
|
|
Packit Service |
3749ba |
va_end (va);
|
|
Packit Service |
3749ba |
return_if_reached ();
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
va_end (va);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
p11_array_free (parser->formats);
|
|
Packit Service |
3749ba |
parser->formats = formats;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
int
|
|
Packit Service |
3749ba |
p11_parse_memory (p11_parser *parser,
|
|
Packit Service |
3749ba |
const char *filename,
|
|
Packit Service |
3749ba |
int flags,
|
|
Packit Service |
3749ba |
const unsigned char *data,
|
|
Packit Service |
3749ba |
size_t length)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
int ret = P11_PARSE_UNRECOGNIZED;
|
|
Packit Service |
3749ba |
char *base;
|
|
Packit Service |
3749ba |
int i;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
return_val_if_fail (parser != NULL, P11_PARSE_FAILURE);
|
|
Packit Service |
3749ba |
return_val_if_fail (filename != NULL, P11_PARSE_FAILURE);
|
|
Packit Service |
3749ba |
return_val_if_fail (parser->formats != NULL, P11_PARSE_FAILURE);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
p11_array_clear (parser->parsed);
|
|
Packit Service |
3749ba |
base = p11_path_base (filename);
|
|
Packit Service |
3749ba |
parser->basename = base;
|
|
Packit Service |
3749ba |
parser->flags = flags;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
for (i = 0; ret == P11_PARSE_UNRECOGNIZED && i < parser->formats->num; i++)
|
|
Packit Service |
3749ba |
ret = ((parser_func)parser->formats->elem[i]) (parser, data, length);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
p11_asn1_cache_flush (parser->asn1_cache);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
free (base);
|
|
Packit Service |
3749ba |
parser->basename = NULL;
|
|
Packit Service |
3749ba |
parser->flags = 0;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
return ret;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
int
|
|
Packit Service |
3749ba |
p11_parse_file (p11_parser *parser,
|
|
Packit Service |
3749ba |
const char *filename,
|
|
Packit Service |
3749ba |
struct stat *sb,
|
|
Packit Service |
3749ba |
int flags)
|
|
Packit Service |
3749ba |
{
|
|
Packit Service |
3749ba |
p11_mmap *map;
|
|
Packit Service |
3749ba |
void *data;
|
|
Packit Service |
3749ba |
size_t size;
|
|
Packit Service |
3749ba |
int ret;
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
return_val_if_fail (parser != NULL, P11_PARSE_FAILURE);
|
|
Packit Service |
3749ba |
return_val_if_fail (filename != NULL, P11_PARSE_FAILURE);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
map = p11_mmap_open (filename, sb, &data, &size);
|
|
Packit Service |
3749ba |
if (map == NULL) {
|
|
Packit Service |
3749ba |
p11_message_err (errno, "couldn't open and map file: %s", filename);
|
|
Packit Service |
3749ba |
return P11_PARSE_FAILURE;
|
|
Packit Service |
3749ba |
}
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
ret = p11_parse_memory (parser, filename, flags, data, size);
|
|
Packit Service |
3749ba |
|
|
Packit Service |
3749ba |
p11_mmap_close (map);
|
|
Packit Service |
3749ba |
return ret;
|
|
Packit Service |
3749ba |
}
|