#include <stdio.h>
#include <openssl/asn1.h>
#include <openssl/objects.h>
#include <openssl/stack.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "err_local.h"
#include "x509_local.h"
int
X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *exts)
{
if (exts == NULL)
return 0;
return sk_X509_EXTENSION_num(exts);
}
LCRYPTO_ALIAS(X509v3_get_ext_count);
int
X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *exts, int nid, int lastpos)
{
const ASN1_OBJECT *obj;
if ((obj = OBJ_nid2obj(nid)) == NULL)
return -2;
return X509v3_get_ext_by_OBJ(exts, obj, lastpos);
}
LCRYPTO_ALIAS(X509v3_get_ext_by_NID);
int
X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *exts,
const ASN1_OBJECT *obj, int lastpos)
{
if (++lastpos < 0)
lastpos = 0;
for (; lastpos < X509v3_get_ext_count(exts); lastpos++) {
const X509_EXTENSION *ext = X509v3_get_ext(exts, lastpos);
if (OBJ_cmp(ext->object, obj) == 0)
return lastpos;
}
return -1;
}
LCRYPTO_ALIAS(X509v3_get_ext_by_OBJ);
int
X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *exts, int critical,
int lastpos)
{
critical = (critical != 0);
if (++lastpos < 0)
lastpos = 0;
for (; lastpos < X509v3_get_ext_count(exts); lastpos++) {
const X509_EXTENSION *ext = X509v3_get_ext(exts, lastpos);
if (X509_EXTENSION_get_critical(ext) == critical)
return lastpos;
}
return -1;
}
LCRYPTO_ALIAS(X509v3_get_ext_by_critical);
X509_EXTENSION *
X509v3_get_ext(const STACK_OF(X509_EXTENSION) *exts, int loc)
{
return sk_X509_EXTENSION_value(exts, loc);
}
LCRYPTO_ALIAS(X509v3_get_ext);
X509_EXTENSION *
X509v3_delete_ext(STACK_OF(X509_EXTENSION) *exts, int loc)
{
return sk_X509_EXTENSION_delete(exts, loc);
}
LCRYPTO_ALIAS(X509v3_delete_ext);
STACK_OF(X509_EXTENSION) *
X509v3_add_ext(STACK_OF(X509_EXTENSION) **out_exts, X509_EXTENSION *ext, int loc)
{
STACK_OF(X509_EXTENSION) *exts = NULL;
X509_EXTENSION *new_ext = NULL;
if (out_exts == NULL) {
X509error(ERR_R_PASSED_NULL_PARAMETER);
goto err;
}
if ((exts = *out_exts) == NULL)
exts = sk_X509_EXTENSION_new_null();
if (exts == NULL) {
X509error(ERR_R_MALLOC_FAILURE);
goto err;
}
if ((new_ext = X509_EXTENSION_dup(ext)) == NULL)
goto err;
if (!sk_X509_EXTENSION_insert(exts, new_ext, loc))
goto err;
new_ext = NULL;
*out_exts = exts;
return exts;
err:
X509_EXTENSION_free(new_ext);
if (out_exts != NULL && exts != *out_exts)
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
return NULL;
}
LCRYPTO_ALIAS(X509v3_add_ext);
X509_EXTENSION *
X509_EXTENSION_create_by_NID(X509_EXTENSION **out_ext, int nid, int critical,
ASN1_OCTET_STRING *data)
{
const ASN1_OBJECT *obj;
if ((obj = OBJ_nid2obj(nid)) == NULL) {
X509error(X509_R_UNKNOWN_NID);
return NULL;
}
return X509_EXTENSION_create_by_OBJ(out_ext, obj, critical, data);
}
LCRYPTO_ALIAS(X509_EXTENSION_create_by_NID);
X509_EXTENSION *
X509_EXTENSION_create_by_OBJ(X509_EXTENSION **out_ext, const ASN1_OBJECT *obj,
int critical, ASN1_OCTET_STRING *data)
{
X509_EXTENSION *ext;
if (out_ext == NULL || (ext = *out_ext) == NULL)
ext = X509_EXTENSION_new();
if (ext == NULL) {
X509error(ERR_R_MALLOC_FAILURE);
goto err;
}
if (!X509_EXTENSION_set_object(ext, obj))
goto err;
if (!X509_EXTENSION_set_critical(ext, critical))
goto err;
if (!X509_EXTENSION_set_data(ext, data))
goto err;
if (out_ext != NULL)
*out_ext = ext;
return ext;
err:
if (out_ext == NULL || ext != *out_ext)
X509_EXTENSION_free(ext);
return NULL;
}
LCRYPTO_ALIAS(X509_EXTENSION_create_by_OBJ);
int
X509_EXTENSION_set_object(X509_EXTENSION *ext, const ASN1_OBJECT *obj)
{
if (ext == NULL || obj == NULL)
return 0;
ASN1_OBJECT_free(ext->object);
return (ext->object = OBJ_dup(obj)) != NULL;
}
LCRYPTO_ALIAS(X509_EXTENSION_set_object);
int
X509_EXTENSION_set_critical(X509_EXTENSION *ext, int critical)
{
if (ext == NULL)
return 0;
ext->critical = critical ? 0xFF : -1;
return 1;
}
LCRYPTO_ALIAS(X509_EXTENSION_set_critical);
int
X509_EXTENSION_set_data(X509_EXTENSION *ext, ASN1_OCTET_STRING *data)
{
if (ext == NULL)
return 0;
return ASN1_STRING_set(ext->value, data->data, data->length);
}
LCRYPTO_ALIAS(X509_EXTENSION_set_data);
ASN1_OBJECT *
X509_EXTENSION_get_object(X509_EXTENSION *ext)
{
if (ext == NULL)
return NULL;
return ext->object;
}
LCRYPTO_ALIAS(X509_EXTENSION_get_object);
ASN1_OCTET_STRING *
X509_EXTENSION_get_data(X509_EXTENSION *ext)
{
if (ext == NULL)
return NULL;
return ext->value;
}
LCRYPTO_ALIAS(X509_EXTENSION_get_data);
int
X509_EXTENSION_get_critical(const X509_EXTENSION *ext)
{
if (ext == NULL)
return 0;
return ext->critical > 0;
}
LCRYPTO_ALIAS(X509_EXTENSION_get_critical);