/*
* Copyright (C) 2015 Red Hat, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
* This file is part of GnuTLS.
*
* The GnuTLS is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see
*
*/
/* Functions that relate on PKCS7 attribute setting.
*/
#include "gnutls_int.h"
#include
#include
#include "errors.h"
#include
#include
#include
#include
/**
* gnutls_pkcs7_add_attr:
* @list: A list of existing attributes or pointer to %NULL for the first one
* @oid: the OID of the attribute to be set
* @data: the raw (DER-encoded) data of the attribute to be set
* @flags: zero or %GNUTLS_PKCS7_ATTR_ENCODE_OCTET_STRING
*
* This function will set a PKCS #7 attribute in the provided list.
* If this function fails, the previous list would be deallocated.
*
* Note that any attributes set with this function must either be
* DER or BER encoded, unless a special flag is present.
*
* Returns: On success, the new list head, otherwise %NULL.
*
* Since: 3.4.2
**/
int
gnutls_pkcs7_add_attr(gnutls_pkcs7_attrs_t * list, const char *oid,
gnutls_datum_t * data, unsigned flags)
{
int ret;
gnutls_pkcs7_attrs_st *r;
r = gnutls_calloc(1, sizeof(gnutls_pkcs7_attrs_st));
if (r == NULL)
goto fail;
if (flags & GNUTLS_PKCS7_ATTR_ENCODE_OCTET_STRING) {
ret = _gnutls_x509_encode_string(ASN1_ETYPE_OCTET_STRING,
data->data, data->size,
&r->data);
} else {
ret = _gnutls_set_datum(&r->data, data->data, data->size);
}
if (ret < 0)
goto fail;
r->oid = gnutls_strdup(oid);
if (r->oid == NULL)
goto fail;
r->next = *list;
*list = r;
return 0;
fail:
if (r) {
gnutls_free(r->data.data);
gnutls_free(r);
}
gnutls_pkcs7_attrs_deinit(*list);
return GNUTLS_E_MEMORY_ERROR;
}
/**
* gnutls_pkcs7_get_attr:
* @list: A list of existing attributes or %NULL for the first one
* @idx: the index of the attribute to get
* @oid: the OID of the attribute (read-only)
* @data: the raw data of the attribute
* @flags: zero or %GNUTLS_PKCS7_ATTR_ENCODE_OCTET_STRING
*
* This function will get a PKCS #7 attribute from the provided list.
* The OID is a constant string, but data will be allocated and must be
* deinitialized by the caller.
*
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
* negative error value. %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned
* if there are no data in the current index.
*
* Since: 3.4.2
**/
int
gnutls_pkcs7_get_attr(gnutls_pkcs7_attrs_t list, unsigned idx, char **oid,
gnutls_datum_t * data, unsigned flags)
{
unsigned i;
gnutls_pkcs7_attrs_st *p = list;
int ret;
for (i = 0; i < idx; i++) {
p = p->next;
if (p == NULL)
break;
}
if (p == NULL)
return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
*oid = p->oid;
if (flags & GNUTLS_PKCS7_ATTR_ENCODE_OCTET_STRING) {
ret = _gnutls_x509_decode_string(ASN1_ETYPE_OCTET_STRING,
p->data.data, p->data.size,
data, 1);
} else {
ret = _gnutls_set_datum(data, p->data.data, p->data.size);
}
if (ret < 0)
return gnutls_assert_val(ret);
return 0;
}
/**
* gnutls_pkcs7_attrs_deinit:
* @list: A list of existing attributes
*
* This function will clear a PKCS #7 attribute list.
*
* Since: 3.4.2
**/
void gnutls_pkcs7_attrs_deinit(gnutls_pkcs7_attrs_t list)
{
gnutls_pkcs7_attrs_st *r = list, *next;
while (r) {
next = r->next;
gnutls_free(r->data.data);
gnutls_free(r->oid);
gnutls_free(r);
r = next;
}
}