/*
* COPYRIGHT (c) International Business Machines Corp. 2012-2017
*
* This program is provided under the terms of the Common Public License,
* version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
* software constitutes recipient's acceptance of CPL-1.0 terms which can be
* found in the file LICENSE file or at
* https://opensource.org/licenses/cpl1.0.php
*/
/*
* OpenCryptoki ICSF token - LDAP functions
*
* Author: Marcelo Cerri (mhcerri@br.ibm.com)
*
*/
#include <stdlib.h>
#include <string.h>
#include "attributes.h"
#include "defs.h"
#include "host_defs.h"
#include "h_extern.h"
#include "trace.h"
#include <openssl/crypto.h>
static void __cleanse_and_free_attribute_array(CK_ATTRIBUTE_PTR attrs,
CK_ULONG attrs_len,
CK_BBOOL cleanse)
{
CK_ULONG i;
if (!attrs)
return;
for (i = 0; i < attrs_len; i++)
if (attrs[i].pValue) {
if (cleanse)
OPENSSL_cleanse(attrs[i].pValue, attrs[i].ulValueLen);
free(attrs[i].pValue);
}
free(attrs);
}
/*
* Free an array of attributes allocated with dup_attribute_array().
*/
void free_attribute_array(CK_ATTRIBUTE_PTR attrs, CK_ULONG attrs_len)
{
__cleanse_and_free_attribute_array(attrs, attrs_len, FALSE);
}
/*
* Free an array of attributes allocated with dup_attribute_array() and cleanse
* all attribute values.
*/
void cleanse_and_free_attribute_array(CK_ATTRIBUTE_PTR attrs,
CK_ULONG attrs_len)
{
__cleanse_and_free_attribute_array(attrs, attrs_len, TRUE);
}
/*
* Duplicate an array of attributes and all its values.
*
* The returned array must be freed with free_attribute_array().
*/
CK_RV dup_attribute_array(CK_ATTRIBUTE_PTR orig, CK_ULONG orig_len,
CK_ATTRIBUTE_PTR *p_dest, CK_ULONG *p_dest_len)
{
CK_RV rc = CKR_OK;
CK_ATTRIBUTE_PTR dest;
CK_ULONG dest_len;
CK_ATTRIBUTE_PTR it;
/* Allocate the new array */
dest_len = orig_len;
dest = malloc(dest_len * sizeof(*dest));
if (dest == NULL) {
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
memset(dest, 0, dest_len);
/* Copy each element */
for (it = dest; it != (dest + orig_len); it++, orig++) {
it->type = orig->type;
it->ulValueLen = orig->ulValueLen;
it->pValue = malloc(it->ulValueLen);
if (it->pValue == NULL) {
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
rc = CKR_HOST_MEMORY;
goto done;
}
memcpy(it->pValue, orig->pValue, orig->ulValueLen);
}
done:
if (rc == CKR_OK) {
*p_dest = dest;
*p_dest_len = dest_len;
} else {
free_attribute_array(dest, dest_len);
}
return rc;
}
/*
* Return the attribute structure for a given type.
*/
CK_ATTRIBUTE_PTR get_attribute_by_type(CK_ATTRIBUTE_PTR attrs,
CK_ULONG attrs_len, CK_ULONG type)
{
CK_ATTRIBUTE_PTR it;
for (it = attrs; it != attrs + attrs_len; it++)
if (it->type == type)
return it;
return NULL;
}
/*
* Reallocate the attribute array and add the new element.
*/
CK_RV add_to_attribute_array(CK_ATTRIBUTE_PTR *p_attrs,
CK_ULONG_PTR p_attrs_len, CK_ULONG type,
CK_BYTE_PTR value, CK_ULONG value_len)
{
CK_ATTRIBUTE_PTR attrs;
CK_BYTE_PTR copied_value;
copied_value = malloc(value_len);
if (copied_value == NULL) {
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
memcpy(copied_value, value, value_len);
attrs = realloc(*p_attrs, sizeof(**p_attrs) * (*p_attrs_len + 1));
if (attrs == NULL) {
free(copied_value);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
attrs[*p_attrs_len].type = type;
attrs[*p_attrs_len].pValue = copied_value;
attrs[*p_attrs_len].ulValueLen = value_len;
*p_attrs = attrs;
*p_attrs_len += 1;
return CKR_OK;
}