1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

Upgrade openssl from 1.1.0e to 1.1.1b, with source code. 4.0.78

This commit is contained in:
winlin 2021-03-01 20:47:57 +08:00
parent 8f1c992379
commit 96dbd7bced
1476 changed files with 616554 additions and 4 deletions

View file

@ -0,0 +1,10 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
x509_def.c x509_d2.c x509_r2x.c x509_cmp.c \
x509_obj.c x509_req.c x509spki.c x509_vfy.c \
x509_set.c x509cset.c x509rset.c x509_err.c \
x509name.c x509_v3.c x509_ext.c x509_att.c \
x509type.c x509_meth.c x509_lu.c x_all.c x509_txt.c \
x509_trs.c by_file.c by_dir.c x509_vpm.c \
x_crl.c t_crl.c x_req.c t_req.c x_x509.c t_x509.c \
x_pubkey.c x_x509a.c x_attrib.c x_exten.c x_name.c

View file

@ -0,0 +1,390 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "e_os.h"
#include "internal/cryptlib.h"
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <sys/types.h>
#ifndef OPENSSL_NO_POSIX_IO
# include <sys/stat.h>
#endif
#include <openssl/x509.h>
#include "internal/x509_int.h"
#include "x509_lcl.h"
struct lookup_dir_hashes_st {
unsigned long hash;
int suffix;
};
struct lookup_dir_entry_st {
char *dir;
int dir_type;
STACK_OF(BY_DIR_HASH) *hashes;
};
typedef struct lookup_dir_st {
BUF_MEM *buffer;
STACK_OF(BY_DIR_ENTRY) *dirs;
CRYPTO_RWLOCK *lock;
} BY_DIR;
static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
char **ret);
static int new_dir(X509_LOOKUP *lu);
static void free_dir(X509_LOOKUP *lu);
static int add_cert_dir(BY_DIR *ctx, const char *dir, int type);
static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
X509_NAME *name, X509_OBJECT *ret);
static X509_LOOKUP_METHOD x509_dir_lookup = {
"Load certs from files in a directory",
new_dir, /* new_item */
free_dir, /* free */
NULL, /* init */
NULL, /* shutdown */
dir_ctrl, /* ctrl */
get_cert_by_subject, /* get_by_subject */
NULL, /* get_by_issuer_serial */
NULL, /* get_by_fingerprint */
NULL, /* get_by_alias */
};
X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void)
{
return &x509_dir_lookup;
}
static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
char **retp)
{
int ret = 0;
BY_DIR *ld = (BY_DIR *)ctx->method_data;
switch (cmd) {
case X509_L_ADD_DIR:
if (argl == X509_FILETYPE_DEFAULT) {
const char *dir = ossl_safe_getenv(X509_get_default_cert_dir_env());
if (dir)
ret = add_cert_dir(ld, dir, X509_FILETYPE_PEM);
else
ret = add_cert_dir(ld, X509_get_default_cert_dir(),
X509_FILETYPE_PEM);
if (!ret) {
X509err(X509_F_DIR_CTRL, X509_R_LOADING_CERT_DIR);
}
} else
ret = add_cert_dir(ld, argp, (int)argl);
break;
}
return ret;
}
static int new_dir(X509_LOOKUP *lu)
{
BY_DIR *a = OPENSSL_malloc(sizeof(*a));
if (a == NULL) {
X509err(X509_F_NEW_DIR, ERR_R_MALLOC_FAILURE);
return 0;
}
if ((a->buffer = BUF_MEM_new()) == NULL) {
X509err(X509_F_NEW_DIR, ERR_R_MALLOC_FAILURE);
goto err;
}
a->dirs = NULL;
a->lock = CRYPTO_THREAD_lock_new();
if (a->lock == NULL) {
BUF_MEM_free(a->buffer);
X509err(X509_F_NEW_DIR, ERR_R_MALLOC_FAILURE);
goto err;
}
lu->method_data = a;
return 1;
err:
OPENSSL_free(a);
return 0;
}
static void by_dir_hash_free(BY_DIR_HASH *hash)
{
OPENSSL_free(hash);
}
static int by_dir_hash_cmp(const BY_DIR_HASH *const *a,
const BY_DIR_HASH *const *b)
{
if ((*a)->hash > (*b)->hash)
return 1;
if ((*a)->hash < (*b)->hash)
return -1;
return 0;
}
static void by_dir_entry_free(BY_DIR_ENTRY *ent)
{
OPENSSL_free(ent->dir);
sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free);
OPENSSL_free(ent);
}
static void free_dir(X509_LOOKUP *lu)
{
BY_DIR *a = (BY_DIR *)lu->method_data;
sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free);
BUF_MEM_free(a->buffer);
CRYPTO_THREAD_lock_free(a->lock);
OPENSSL_free(a);
}
static int add_cert_dir(BY_DIR *ctx, const char *dir, int type)
{
int j;
size_t len;
const char *s, *ss, *p;
if (dir == NULL || !*dir) {
X509err(X509_F_ADD_CERT_DIR, X509_R_INVALID_DIRECTORY);
return 0;
}
s = dir;
p = s;
do {
if ((*p == LIST_SEPARATOR_CHAR) || (*p == '\0')) {
BY_DIR_ENTRY *ent;
ss = s;
s = p + 1;
len = p - ss;
if (len == 0)
continue;
for (j = 0; j < sk_BY_DIR_ENTRY_num(ctx->dirs); j++) {
ent = sk_BY_DIR_ENTRY_value(ctx->dirs, j);
if (strlen(ent->dir) == len && strncmp(ent->dir, ss, len) == 0)
break;
}
if (j < sk_BY_DIR_ENTRY_num(ctx->dirs))
continue;
if (ctx->dirs == NULL) {
ctx->dirs = sk_BY_DIR_ENTRY_new_null();
if (!ctx->dirs) {
X509err(X509_F_ADD_CERT_DIR, ERR_R_MALLOC_FAILURE);
return 0;
}
}
ent = OPENSSL_malloc(sizeof(*ent));
if (ent == NULL) {
X509err(X509_F_ADD_CERT_DIR, ERR_R_MALLOC_FAILURE);
return 0;
}
ent->dir_type = type;
ent->hashes = sk_BY_DIR_HASH_new(by_dir_hash_cmp);
ent->dir = OPENSSL_strndup(ss, len);
if (ent->dir == NULL || ent->hashes == NULL) {
by_dir_entry_free(ent);
return 0;
}
if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent)) {
by_dir_entry_free(ent);
X509err(X509_F_ADD_CERT_DIR, ERR_R_MALLOC_FAILURE);
return 0;
}
}
} while (*p++ != '\0');
return 1;
}
static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
X509_NAME *name, X509_OBJECT *ret)
{
BY_DIR *ctx;
union {
X509 st_x509;
X509_CRL crl;
} data;
int ok = 0;
int i, j, k;
unsigned long h;
BUF_MEM *b = NULL;
X509_OBJECT stmp, *tmp;
const char *postfix = "";
if (name == NULL)
return 0;
stmp.type = type;
if (type == X509_LU_X509) {
data.st_x509.cert_info.subject = name;
stmp.data.x509 = &data.st_x509;
postfix = "";
} else if (type == X509_LU_CRL) {
data.crl.crl.issuer = name;
stmp.data.crl = &data.crl;
postfix = "r";
} else {
X509err(X509_F_GET_CERT_BY_SUBJECT, X509_R_WRONG_LOOKUP_TYPE);
goto finish;
}
if ((b = BUF_MEM_new()) == NULL) {
X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_BUF_LIB);
goto finish;
}
ctx = (BY_DIR *)xl->method_data;
h = X509_NAME_hash(name);
for (i = 0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++) {
BY_DIR_ENTRY *ent;
int idx;
BY_DIR_HASH htmp, *hent;
ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i);
j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1;
if (!BUF_MEM_grow(b, j)) {
X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);
goto finish;
}
if (type == X509_LU_CRL && ent->hashes) {
htmp.hash = h;
CRYPTO_THREAD_read_lock(ctx->lock);
idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp);
if (idx >= 0) {
hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
k = hent->suffix;
} else {
hent = NULL;
k = 0;
}
CRYPTO_THREAD_unlock(ctx->lock);
} else {
k = 0;
hent = NULL;
}
for (;;) {
char c = '/';
#ifdef OPENSSL_SYS_VMS
c = ent->dir[strlen(ent->dir) - 1];
if (c != ':' && c != '>' && c != ']') {
/*
* If no separator is present, we assume the directory
* specifier is a logical name, and add a colon. We really
* should use better VMS routines for merging things like
* this, but this will do for now... -- Richard Levitte
*/
c = ':';
} else {
c = '\0';
}
#endif
if (c == '\0') {
/*
* This is special. When c == '\0', no directory separator
* should be added.
*/
BIO_snprintf(b->data, b->max,
"%s%08lx.%s%d", ent->dir, h, postfix, k);
} else {
BIO_snprintf(b->data, b->max,
"%s%c%08lx.%s%d", ent->dir, c, h, postfix, k);
}
#ifndef OPENSSL_NO_POSIX_IO
# ifdef _WIN32
# define stat _stat
# endif
{
struct stat st;
if (stat(b->data, &st) < 0)
break;
}
#endif
/* found one. */
if (type == X509_LU_X509) {
if ((X509_load_cert_file(xl, b->data, ent->dir_type)) == 0)
break;
} else if (type == X509_LU_CRL) {
if ((X509_load_crl_file(xl, b->data, ent->dir_type)) == 0)
break;
}
/* else case will caught higher up */
k++;
}
/*
* we have added it to the cache so now pull it out again
*/
CRYPTO_THREAD_write_lock(ctx->lock);
j = sk_X509_OBJECT_find(xl->store_ctx->objs, &stmp);
tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, j);
CRYPTO_THREAD_unlock(ctx->lock);
/* If a CRL, update the last file suffix added for this */
if (type == X509_LU_CRL) {
CRYPTO_THREAD_write_lock(ctx->lock);
/*
* Look for entry again in case another thread added an entry
* first.
*/
if (hent == NULL) {
htmp.hash = h;
idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp);
hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
}
if (hent == NULL) {
hent = OPENSSL_malloc(sizeof(*hent));
if (hent == NULL) {
CRYPTO_THREAD_unlock(ctx->lock);
X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);
ok = 0;
goto finish;
}
hent->hash = h;
hent->suffix = k;
if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) {
CRYPTO_THREAD_unlock(ctx->lock);
OPENSSL_free(hent);
X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);
ok = 0;
goto finish;
}
} else if (hent->suffix < k) {
hent->suffix = k;
}
CRYPTO_THREAD_unlock(ctx->lock);
}
if (tmp != NULL) {
ok = 1;
ret->type = tmp->type;
memcpy(&ret->data, &tmp->data, sizeof(ret->data));
/*
* Clear any errors that might have been raised processing empty
* or malformed files.
*/
ERR_clear_error();
goto finish;
}
}
finish:
BUF_MEM_free(b);
return ok;
}

View file

@ -0,0 +1,227 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include "internal/cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include "x509_lcl.h"
static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
long argl, char **ret);
static X509_LOOKUP_METHOD x509_file_lookup = {
"Load file into cache",
NULL, /* new_item */
NULL, /* free */
NULL, /* init */
NULL, /* shutdown */
by_file_ctrl, /* ctrl */
NULL, /* get_by_subject */
NULL, /* get_by_issuer_serial */
NULL, /* get_by_fingerprint */
NULL, /* get_by_alias */
};
X509_LOOKUP_METHOD *X509_LOOKUP_file(void)
{
return &x509_file_lookup;
}
static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp,
long argl, char **ret)
{
int ok = 0;
const char *file;
switch (cmd) {
case X509_L_FILE_LOAD:
if (argl == X509_FILETYPE_DEFAULT) {
file = ossl_safe_getenv(X509_get_default_cert_file_env());
if (file)
ok = (X509_load_cert_crl_file(ctx, file,
X509_FILETYPE_PEM) != 0);
else
ok = (X509_load_cert_crl_file
(ctx, X509_get_default_cert_file(),
X509_FILETYPE_PEM) != 0);
if (!ok) {
X509err(X509_F_BY_FILE_CTRL, X509_R_LOADING_DEFAULTS);
}
} else {
if (argl == X509_FILETYPE_PEM)
ok = (X509_load_cert_crl_file(ctx, argp,
X509_FILETYPE_PEM) != 0);
else
ok = (X509_load_cert_file(ctx, argp, (int)argl) != 0);
}
break;
}
return ok;
}
int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type)
{
int ret = 0;
BIO *in = NULL;
int i, count = 0;
X509 *x = NULL;
in = BIO_new(BIO_s_file());
if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) {
X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_SYS_LIB);
goto err;
}
if (type == X509_FILETYPE_PEM) {
for (;;) {
x = PEM_read_bio_X509_AUX(in, NULL, NULL, "");
if (x == NULL) {
if ((ERR_GET_REASON(ERR_peek_last_error()) ==
PEM_R_NO_START_LINE) && (count > 0)) {
ERR_clear_error();
break;
} else {
X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_PEM_LIB);
goto err;
}
}
i = X509_STORE_add_cert(ctx->store_ctx, x);
if (!i)
goto err;
count++;
X509_free(x);
x = NULL;
}
ret = count;
} else if (type == X509_FILETYPE_ASN1) {
x = d2i_X509_bio(in, NULL);
if (x == NULL) {
X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_ASN1_LIB);
goto err;
}
i = X509_STORE_add_cert(ctx->store_ctx, x);
if (!i)
goto err;
ret = i;
} else {
X509err(X509_F_X509_LOAD_CERT_FILE, X509_R_BAD_X509_FILETYPE);
goto err;
}
if (ret == 0)
X509err(X509_F_X509_LOAD_CERT_FILE, X509_R_NO_CERTIFICATE_FOUND);
err:
X509_free(x);
BIO_free(in);
return ret;
}
int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type)
{
int ret = 0;
BIO *in = NULL;
int i, count = 0;
X509_CRL *x = NULL;
in = BIO_new(BIO_s_file());
if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) {
X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_SYS_LIB);
goto err;
}
if (type == X509_FILETYPE_PEM) {
for (;;) {
x = PEM_read_bio_X509_CRL(in, NULL, NULL, "");
if (x == NULL) {
if ((ERR_GET_REASON(ERR_peek_last_error()) ==
PEM_R_NO_START_LINE) && (count > 0)) {
ERR_clear_error();
break;
} else {
X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_PEM_LIB);
goto err;
}
}
i = X509_STORE_add_crl(ctx->store_ctx, x);
if (!i)
goto err;
count++;
X509_CRL_free(x);
x = NULL;
}
ret = count;
} else if (type == X509_FILETYPE_ASN1) {
x = d2i_X509_CRL_bio(in, NULL);
if (x == NULL) {
X509err(X509_F_X509_LOAD_CRL_FILE, ERR_R_ASN1_LIB);
goto err;
}
i = X509_STORE_add_crl(ctx->store_ctx, x);
if (!i)
goto err;
ret = i;
} else {
X509err(X509_F_X509_LOAD_CRL_FILE, X509_R_BAD_X509_FILETYPE);
goto err;
}
if (ret == 0)
X509err(X509_F_X509_LOAD_CRL_FILE, X509_R_NO_CRL_FOUND);
err:
X509_CRL_free(x);
BIO_free(in);
return ret;
}
int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type)
{
STACK_OF(X509_INFO) *inf;
X509_INFO *itmp;
BIO *in;
int i, count = 0;
if (type != X509_FILETYPE_PEM)
return X509_load_cert_file(ctx, file, type);
in = BIO_new_file(file, "r");
if (!in) {
X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_SYS_LIB);
return 0;
}
inf = PEM_X509_INFO_read_bio(in, NULL, NULL, "");
BIO_free(in);
if (!inf) {
X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_PEM_LIB);
return 0;
}
for (i = 0; i < sk_X509_INFO_num(inf); i++) {
itmp = sk_X509_INFO_value(inf, i);
if (itmp->x509) {
if (!X509_STORE_add_cert(ctx->store_ctx, itmp->x509))
goto err;
count++;
}
if (itmp->crl) {
if (!X509_STORE_add_crl(ctx->store_ctx, itmp->crl))
goto err;
count++;
}
}
if (count == 0)
X509err(X509_F_X509_LOAD_CERT_CRL_FILE,
X509_R_NO_CERTIFICATE_OR_CRL_FOUND);
err:
sk_X509_INFO_pop_free(inf, X509_INFO_free);
return count;
}

View file

@ -0,0 +1,94 @@
/*
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/bn.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#ifndef OPENSSL_NO_STDIO
int X509_CRL_print_fp(FILE *fp, X509_CRL *x)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
X509err(X509_F_X509_CRL_PRINT_FP, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
ret = X509_CRL_print(b, x);
BIO_free(b);
return ret;
}
#endif
int X509_CRL_print(BIO *out, X509_CRL *x)
{
return X509_CRL_print_ex(out, x, XN_FLAG_COMPAT);
}
int X509_CRL_print_ex(BIO *out, X509_CRL *x, unsigned long nmflag)
{
STACK_OF(X509_REVOKED) *rev;
X509_REVOKED *r;
const X509_ALGOR *sig_alg;
const ASN1_BIT_STRING *sig;
long l;
int i;
BIO_printf(out, "Certificate Revocation List (CRL):\n");
l = X509_CRL_get_version(x);
if (l >= 0 && l <= 1)
BIO_printf(out, "%8sVersion %ld (0x%lx)\n", "", l + 1, (unsigned long)l);
else
BIO_printf(out, "%8sVersion unknown (%ld)\n", "", l);
X509_CRL_get0_signature(x, &sig, &sig_alg);
BIO_puts(out, " ");
X509_signature_print(out, sig_alg, NULL);
BIO_printf(out, "%8sIssuer: ", "");
X509_NAME_print_ex(out, X509_CRL_get_issuer(x), 0, nmflag);
BIO_puts(out, "\n");
BIO_printf(out, "%8sLast Update: ", "");
ASN1_TIME_print(out, X509_CRL_get0_lastUpdate(x));
BIO_printf(out, "\n%8sNext Update: ", "");
if (X509_CRL_get0_nextUpdate(x))
ASN1_TIME_print(out, X509_CRL_get0_nextUpdate(x));
else
BIO_printf(out, "NONE");
BIO_printf(out, "\n");
X509V3_extensions_print(out, "CRL extensions",
X509_CRL_get0_extensions(x), 0, 8);
rev = X509_CRL_get_REVOKED(x);
if (sk_X509_REVOKED_num(rev) > 0)
BIO_printf(out, "Revoked Certificates:\n");
else
BIO_printf(out, "No Revoked Certificates.\n");
for (i = 0; i < sk_X509_REVOKED_num(rev); i++) {
r = sk_X509_REVOKED_value(rev, i);
BIO_printf(out, " Serial Number: ");
i2a_ASN1_INTEGER(out, X509_REVOKED_get0_serialNumber(r));
BIO_printf(out, "\n Revocation Date: ");
ASN1_TIME_print(out, X509_REVOKED_get0_revocationDate(r));
BIO_printf(out, "\n");
X509V3_extensions_print(out, "CRL entry extensions",
X509_REVOKED_get0_extensions(r), 0, 8);
}
X509_signature_print(out, sig_alg, sig);
return 1;
}

View file

@ -0,0 +1,210 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/bn.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#ifndef OPENSSL_NO_STDIO
int X509_REQ_print_fp(FILE *fp, X509_REQ *x)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
X509err(X509_F_X509_REQ_PRINT_FP, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
ret = X509_REQ_print(b, x);
BIO_free(b);
return ret;
}
#endif
int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags,
unsigned long cflag)
{
long l;
int i;
EVP_PKEY *pkey;
STACK_OF(X509_EXTENSION) *exts;
char mlch = ' ';
int nmindent = 0;
if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
mlch = '\n';
nmindent = 12;
}
if (nmflags == X509_FLAG_COMPAT)
nmindent = 16;
if (!(cflag & X509_FLAG_NO_HEADER)) {
if (BIO_write(bp, "Certificate Request:\n", 21) <= 0)
goto err;
if (BIO_write(bp, " Data:\n", 10) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_VERSION)) {
l = X509_REQ_get_version(x);
if (l >= 0 && l <= 2) {
if (BIO_printf(bp, "%8sVersion: %ld (0x%lx)\n", "", l + 1, (unsigned long)l) <= 0)
goto err;
} else {
if (BIO_printf(bp, "%8sVersion: Unknown (%ld)\n", "", l) <= 0)
goto err;
}
}
if (!(cflag & X509_FLAG_NO_SUBJECT)) {
if (BIO_printf(bp, " Subject:%c", mlch) <= 0)
goto err;
if (X509_NAME_print_ex(bp, X509_REQ_get_subject_name(x),
nmindent, nmflags) < 0)
goto err;
if (BIO_write(bp, "\n", 1) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_PUBKEY)) {
X509_PUBKEY *xpkey;
ASN1_OBJECT *koid;
if (BIO_write(bp, " Subject Public Key Info:\n", 33) <= 0)
goto err;
if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0)
goto err;
xpkey = X509_REQ_get_X509_PUBKEY(x);
X509_PUBKEY_get0_param(&koid, NULL, NULL, NULL, xpkey);
if (i2a_ASN1_OBJECT(bp, koid) <= 0)
goto err;
if (BIO_puts(bp, "\n") <= 0)
goto err;
pkey = X509_REQ_get0_pubkey(x);
if (pkey == NULL) {
if (BIO_printf(bp, "%12sUnable to load Public Key\n", "") <= 0)
goto err;
ERR_print_errors(bp);
} else {
if (EVP_PKEY_print_public(bp, pkey, 16, NULL) <= 0)
goto err;
}
}
if (!(cflag & X509_FLAG_NO_ATTRIBUTES)) {
/* may not be */
if (BIO_printf(bp, "%8sAttributes:\n", "") <= 0)
goto err;
if (X509_REQ_get_attr_count(x) == 0) {
if (BIO_printf(bp, "%12sa0:00\n", "") <= 0)
goto err;
} else {
for (i = 0; i < X509_REQ_get_attr_count(x); i++) {
ASN1_TYPE *at;
X509_ATTRIBUTE *a;
ASN1_BIT_STRING *bs = NULL;
ASN1_OBJECT *aobj;
int j, type = 0, count = 1, ii = 0;
a = X509_REQ_get_attr(x, i);
aobj = X509_ATTRIBUTE_get0_object(a);
if (X509_REQ_extension_nid(OBJ_obj2nid(aobj)))
continue;
if (BIO_printf(bp, "%12s", "") <= 0)
goto err;
if ((j = i2a_ASN1_OBJECT(bp, aobj)) > 0) {
ii = 0;
count = X509_ATTRIBUTE_count(a);
get_next:
at = X509_ATTRIBUTE_get0_type(a, ii);
type = at->type;
bs = at->value.asn1_string;
}
for (j = 25 - j; j > 0; j--)
if (BIO_write(bp, " ", 1) != 1)
goto err;
if (BIO_puts(bp, ":") <= 0)
goto err;
switch (type) {
case V_ASN1_PRINTABLESTRING:
case V_ASN1_T61STRING:
case V_ASN1_NUMERICSTRING:
case V_ASN1_UTF8STRING:
case V_ASN1_IA5STRING:
if (BIO_write(bp, (char *)bs->data, bs->length)
!= bs->length)
goto err;
if (BIO_puts(bp, "\n") <= 0)
goto err;
break;
default:
if (BIO_puts(bp, "unable to print attribute\n") <= 0)
goto err;
break;
}
if (++ii < count)
goto get_next;
}
}
}
if (!(cflag & X509_FLAG_NO_EXTENSIONS)) {
exts = X509_REQ_get_extensions(x);
if (exts) {
if (BIO_printf(bp, "%8sRequested Extensions:\n", "") <= 0)
goto err;
for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
ASN1_OBJECT *obj;
X509_EXTENSION *ex;
int critical;
ex = sk_X509_EXTENSION_value(exts, i);
if (BIO_printf(bp, "%12s", "") <= 0)
goto err;
obj = X509_EXTENSION_get_object(ex);
if (i2a_ASN1_OBJECT(bp, obj) <= 0)
goto err;
critical = X509_EXTENSION_get_critical(ex);
if (BIO_printf(bp, ": %s\n", critical ? "critical" : "") <= 0)
goto err;
if (!X509V3_EXT_print(bp, ex, cflag, 16)) {
if (BIO_printf(bp, "%16s", "") <= 0
|| ASN1_STRING_print(bp,
X509_EXTENSION_get_data(ex)) <= 0)
goto err;
}
if (BIO_write(bp, "\n", 1) <= 0)
goto err;
}
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
}
}
if (!(cflag & X509_FLAG_NO_SIGDUMP)) {
const X509_ALGOR *sig_alg;
const ASN1_BIT_STRING *sig;
X509_REQ_get0_signature(x, &sig, &sig_alg);
if (!X509_signature_print(bp, sig_alg, sig))
goto err;
}
return 1;
err:
X509err(X509_F_X509_REQ_PRINT_EX, ERR_R_BUF_LIB);
return 0;
}
int X509_REQ_print(BIO *bp, X509_REQ *x)
{
return X509_REQ_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
}

View file

@ -0,0 +1,379 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/bn.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "internal/asn1_int.h"
#ifndef OPENSSL_NO_STDIO
int X509_print_fp(FILE *fp, X509 *x)
{
return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
}
int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag,
unsigned long cflag)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
X509err(X509_F_X509_PRINT_EX_FP, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
ret = X509_print_ex(b, x, nmflag, cflag);
BIO_free(b);
return ret;
}
#endif
int X509_print(BIO *bp, X509 *x)
{
return X509_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
}
int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
unsigned long cflag)
{
long l;
int ret = 0, i;
char *m = NULL, mlch = ' ';
int nmindent = 0;
ASN1_INTEGER *bs;
EVP_PKEY *pkey = NULL;
const char *neg;
if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
mlch = '\n';
nmindent = 12;
}
if (nmflags == X509_FLAG_COMPAT)
nmindent = 16;
if (!(cflag & X509_FLAG_NO_HEADER)) {
if (BIO_write(bp, "Certificate:\n", 13) <= 0)
goto err;
if (BIO_write(bp, " Data:\n", 10) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_VERSION)) {
l = X509_get_version(x);
if (l >= 0 && l <= 2) {
if (BIO_printf(bp, "%8sVersion: %ld (0x%lx)\n", "", l + 1, (unsigned long)l) <= 0)
goto err;
} else {
if (BIO_printf(bp, "%8sVersion: Unknown (%ld)\n", "", l) <= 0)
goto err;
}
}
if (!(cflag & X509_FLAG_NO_SERIAL)) {
if (BIO_write(bp, " Serial Number:", 22) <= 0)
goto err;
bs = X509_get_serialNumber(x);
if (bs->length <= (int)sizeof(long)) {
ERR_set_mark();
l = ASN1_INTEGER_get(bs);
ERR_pop_to_mark();
} else {
l = -1;
}
if (l != -1) {
unsigned long ul;
if (bs->type == V_ASN1_NEG_INTEGER) {
ul = 0 - (unsigned long)l;
neg = "-";
} else {
ul = l;
neg = "";
}
if (BIO_printf(bp, " %s%lu (%s0x%lx)\n", neg, ul, neg, ul) <= 0)
goto err;
} else {
neg = (bs->type == V_ASN1_NEG_INTEGER) ? " (Negative)" : "";
if (BIO_printf(bp, "\n%12s%s", "", neg) <= 0)
goto err;
for (i = 0; i < bs->length; i++) {
if (BIO_printf(bp, "%02x%c", bs->data[i],
((i + 1 == bs->length) ? '\n' : ':')) <= 0)
goto err;
}
}
}
if (!(cflag & X509_FLAG_NO_SIGNAME)) {
const X509_ALGOR *tsig_alg = X509_get0_tbs_sigalg(x);
if (BIO_puts(bp, " ") <= 0)
goto err;
if (X509_signature_print(bp, tsig_alg, NULL) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_ISSUER)) {
if (BIO_printf(bp, " Issuer:%c", mlch) <= 0)
goto err;
if (X509_NAME_print_ex(bp, X509_get_issuer_name(x), nmindent, nmflags)
< 0)
goto err;
if (BIO_write(bp, "\n", 1) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_VALIDITY)) {
if (BIO_write(bp, " Validity\n", 17) <= 0)
goto err;
if (BIO_write(bp, " Not Before: ", 24) <= 0)
goto err;
if (!ASN1_TIME_print(bp, X509_get0_notBefore(x)))
goto err;
if (BIO_write(bp, "\n Not After : ", 25) <= 0)
goto err;
if (!ASN1_TIME_print(bp, X509_get0_notAfter(x)))
goto err;
if (BIO_write(bp, "\n", 1) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_SUBJECT)) {
if (BIO_printf(bp, " Subject:%c", mlch) <= 0)
goto err;
if (X509_NAME_print_ex
(bp, X509_get_subject_name(x), nmindent, nmflags) < 0)
goto err;
if (BIO_write(bp, "\n", 1) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_PUBKEY)) {
X509_PUBKEY *xpkey = X509_get_X509_PUBKEY(x);
ASN1_OBJECT *xpoid;
X509_PUBKEY_get0_param(&xpoid, NULL, NULL, NULL, xpkey);
if (BIO_write(bp, " Subject Public Key Info:\n", 33) <= 0)
goto err;
if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0)
goto err;
if (i2a_ASN1_OBJECT(bp, xpoid) <= 0)
goto err;
if (BIO_puts(bp, "\n") <= 0)
goto err;
pkey = X509_get0_pubkey(x);
if (pkey == NULL) {
BIO_printf(bp, "%12sUnable to load Public Key\n", "");
ERR_print_errors(bp);
} else {
EVP_PKEY_print_public(bp, pkey, 16, NULL);
}
}
if (!(cflag & X509_FLAG_NO_IDS)) {
const ASN1_BIT_STRING *iuid, *suid;
X509_get0_uids(x, &iuid, &suid);
if (iuid != NULL) {
if (BIO_printf(bp, "%8sIssuer Unique ID: ", "") <= 0)
goto err;
if (!X509_signature_dump(bp, iuid, 12))
goto err;
}
if (suid != NULL) {
if (BIO_printf(bp, "%8sSubject Unique ID: ", "") <= 0)
goto err;
if (!X509_signature_dump(bp, suid, 12))
goto err;
}
}
if (!(cflag & X509_FLAG_NO_EXTENSIONS))
X509V3_extensions_print(bp, "X509v3 extensions",
X509_get0_extensions(x), cflag, 8);
if (!(cflag & X509_FLAG_NO_SIGDUMP)) {
const X509_ALGOR *sig_alg;
const ASN1_BIT_STRING *sig;
X509_get0_signature(&sig, &sig_alg, x);
if (X509_signature_print(bp, sig_alg, sig) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_AUX)) {
if (!X509_aux_print(bp, x, 0))
goto err;
}
ret = 1;
err:
OPENSSL_free(m);
return ret;
}
int X509_ocspid_print(BIO *bp, X509 *x)
{
unsigned char *der = NULL;
unsigned char *dertmp;
int derlen;
int i;
unsigned char SHA1md[SHA_DIGEST_LENGTH];
ASN1_BIT_STRING *keybstr;
X509_NAME *subj;
/*
* display the hash of the subject as it would appear in OCSP requests
*/
if (BIO_printf(bp, " Subject OCSP hash: ") <= 0)
goto err;
subj = X509_get_subject_name(x);
derlen = i2d_X509_NAME(subj, NULL);
if ((der = dertmp = OPENSSL_malloc(derlen)) == NULL)
goto err;
i2d_X509_NAME(subj, &dertmp);
if (!EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL))
goto err;
for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0)
goto err;
}
OPENSSL_free(der);
der = NULL;
/*
* display the hash of the public key as it would appear in OCSP requests
*/
if (BIO_printf(bp, "\n Public key OCSP hash: ") <= 0)
goto err;
keybstr = X509_get0_pubkey_bitstr(x);
if (keybstr == NULL)
goto err;
if (!EVP_Digest(ASN1_STRING_get0_data(keybstr),
ASN1_STRING_length(keybstr), SHA1md, NULL, EVP_sha1(),
NULL))
goto err;
for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0)
goto err;
}
BIO_printf(bp, "\n");
return 1;
err:
OPENSSL_free(der);
return 0;
}
int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent)
{
const unsigned char *s;
int i, n;
n = sig->length;
s = sig->data;
for (i = 0; i < n; i++) {
if ((i % 18) == 0) {
if (BIO_write(bp, "\n", 1) <= 0)
return 0;
if (BIO_indent(bp, indent, indent) <= 0)
return 0;
}
if (BIO_printf(bp, "%02x%s", s[i], ((i + 1) == n) ? "" : ":") <= 0)
return 0;
}
if (BIO_write(bp, "\n", 1) != 1)
return 0;
return 1;
}
int X509_signature_print(BIO *bp, const X509_ALGOR *sigalg,
const ASN1_STRING *sig)
{
int sig_nid;
if (BIO_puts(bp, " Signature Algorithm: ") <= 0)
return 0;
if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0)
return 0;
sig_nid = OBJ_obj2nid(sigalg->algorithm);
if (sig_nid != NID_undef) {
int pkey_nid, dig_nid;
const EVP_PKEY_ASN1_METHOD *ameth;
if (OBJ_find_sigid_algs(sig_nid, &dig_nid, &pkey_nid)) {
ameth = EVP_PKEY_asn1_find(NULL, pkey_nid);
if (ameth && ameth->sig_print)
return ameth->sig_print(bp, sigalg, sig, 9, 0);
}
}
if (sig)
return X509_signature_dump(bp, sig, 9);
else if (BIO_puts(bp, "\n") <= 0)
return 0;
return 1;
}
int X509_aux_print(BIO *out, X509 *x, int indent)
{
char oidstr[80], first;
STACK_OF(ASN1_OBJECT) *trust, *reject;
const unsigned char *alias, *keyid;
int keyidlen;
int i;
if (X509_trusted(x) == 0)
return 1;
trust = X509_get0_trust_objects(x);
reject = X509_get0_reject_objects(x);
if (trust) {
first = 1;
BIO_printf(out, "%*sTrusted Uses:\n%*s", indent, "", indent + 2, "");
for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) {
if (!first)
BIO_puts(out, ", ");
else
first = 0;
OBJ_obj2txt(oidstr, sizeof(oidstr),
sk_ASN1_OBJECT_value(trust, i), 0);
BIO_puts(out, oidstr);
}
BIO_puts(out, "\n");
} else
BIO_printf(out, "%*sNo Trusted Uses.\n", indent, "");
if (reject) {
first = 1;
BIO_printf(out, "%*sRejected Uses:\n%*s", indent, "", indent + 2, "");
for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) {
if (!first)
BIO_puts(out, ", ");
else
first = 0;
OBJ_obj2txt(oidstr, sizeof(oidstr),
sk_ASN1_OBJECT_value(reject, i), 0);
BIO_puts(out, oidstr);
}
BIO_puts(out, "\n");
} else
BIO_printf(out, "%*sNo Rejected Uses.\n", indent, "");
alias = X509_alias_get0(x, NULL);
if (alias)
BIO_printf(out, "%*sAlias: %s\n", indent, "", alias);
keyid = X509_keyid_get0(x, &keyidlen);
if (keyid) {
BIO_printf(out, "%*sKey Id: ", indent, "");
for (i = 0; i < keyidlen; i++)
BIO_printf(out, "%s%02X", i ? ":" : "", keyid[i]);
BIO_write(out, "\n", 1);
}
return 1;
}

View file

@ -0,0 +1,329 @@
/*
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/safestack.h>
#include <openssl/asn1.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "x509_lcl.h"
int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x)
{
return sk_X509_ATTRIBUTE_num(x);
}
int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid,
int lastpos)
{
const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
if (obj == NULL)
return -2;
return X509at_get_attr_by_OBJ(x, obj, lastpos);
}
int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk,
const ASN1_OBJECT *obj, int lastpos)
{
int n;
X509_ATTRIBUTE *ex;
if (sk == NULL)
return -1;
lastpos++;
if (lastpos < 0)
lastpos = 0;
n = sk_X509_ATTRIBUTE_num(sk);
for (; lastpos < n; lastpos++) {
ex = sk_X509_ATTRIBUTE_value(sk, lastpos);
if (OBJ_cmp(ex->object, obj) == 0)
return lastpos;
}
return -1;
}
X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc)
{
if (x == NULL || sk_X509_ATTRIBUTE_num(x) <= loc || loc < 0)
return NULL;
return sk_X509_ATTRIBUTE_value(x, loc);
}
X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc)
{
X509_ATTRIBUTE *ret;
if (x == NULL || sk_X509_ATTRIBUTE_num(x) <= loc || loc < 0)
return NULL;
ret = sk_X509_ATTRIBUTE_delete(x, loc);
return ret;
}
STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x,
X509_ATTRIBUTE *attr)
{
X509_ATTRIBUTE *new_attr = NULL;
STACK_OF(X509_ATTRIBUTE) *sk = NULL;
if (x == NULL) {
X509err(X509_F_X509AT_ADD1_ATTR, ERR_R_PASSED_NULL_PARAMETER);
goto err2;
}
if (*x == NULL) {
if ((sk = sk_X509_ATTRIBUTE_new_null()) == NULL)
goto err;
} else
sk = *x;
if ((new_attr = X509_ATTRIBUTE_dup(attr)) == NULL)
goto err2;
if (!sk_X509_ATTRIBUTE_push(sk, new_attr))
goto err;
if (*x == NULL)
*x = sk;
return sk;
err:
X509err(X509_F_X509AT_ADD1_ATTR, ERR_R_MALLOC_FAILURE);
err2:
X509_ATTRIBUTE_free(new_attr);
sk_X509_ATTRIBUTE_free(sk);
return NULL;
}
STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE)
**x, const ASN1_OBJECT *obj,
int type,
const unsigned char *bytes,
int len)
{
X509_ATTRIBUTE *attr;
STACK_OF(X509_ATTRIBUTE) *ret;
attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, type, bytes, len);
if (!attr)
return 0;
ret = X509at_add1_attr(x, attr);
X509_ATTRIBUTE_free(attr);
return ret;
}
STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE)
**x, int nid, int type,
const unsigned char *bytes,
int len)
{
X509_ATTRIBUTE *attr;
STACK_OF(X509_ATTRIBUTE) *ret;
attr = X509_ATTRIBUTE_create_by_NID(NULL, nid, type, bytes, len);
if (!attr)
return 0;
ret = X509at_add1_attr(x, attr);
X509_ATTRIBUTE_free(attr);
return ret;
}
STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE)
**x, const char *attrname,
int type,
const unsigned char *bytes,
int len)
{
X509_ATTRIBUTE *attr;
STACK_OF(X509_ATTRIBUTE) *ret;
attr = X509_ATTRIBUTE_create_by_txt(NULL, attrname, type, bytes, len);
if (!attr)
return 0;
ret = X509at_add1_attr(x, attr);
X509_ATTRIBUTE_free(attr);
return ret;
}
void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x,
const ASN1_OBJECT *obj, int lastpos, int type)
{
int i;
X509_ATTRIBUTE *at;
i = X509at_get_attr_by_OBJ(x, obj, lastpos);
if (i == -1)
return NULL;
if ((lastpos <= -2) && (X509at_get_attr_by_OBJ(x, obj, i) != -1))
return NULL;
at = X509at_get_attr(x, i);
if (lastpos <= -3 && (X509_ATTRIBUTE_count(at) != 1))
return NULL;
return X509_ATTRIBUTE_get0_data(at, 0, type, NULL);
}
X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid,
int atrtype, const void *data,
int len)
{
ASN1_OBJECT *obj;
X509_ATTRIBUTE *ret;
obj = OBJ_nid2obj(nid);
if (obj == NULL) {
X509err(X509_F_X509_ATTRIBUTE_CREATE_BY_NID, X509_R_UNKNOWN_NID);
return NULL;
}
ret = X509_ATTRIBUTE_create_by_OBJ(attr, obj, atrtype, data, len);
if (ret == NULL)
ASN1_OBJECT_free(obj);
return ret;
}
X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr,
const ASN1_OBJECT *obj,
int atrtype, const void *data,
int len)
{
X509_ATTRIBUTE *ret;
if ((attr == NULL) || (*attr == NULL)) {
if ((ret = X509_ATTRIBUTE_new()) == NULL) {
X509err(X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ,
ERR_R_MALLOC_FAILURE);
return NULL;
}
} else
ret = *attr;
if (!X509_ATTRIBUTE_set1_object(ret, obj))
goto err;
if (!X509_ATTRIBUTE_set1_data(ret, atrtype, data, len))
goto err;
if ((attr != NULL) && (*attr == NULL))
*attr = ret;
return ret;
err:
if ((attr == NULL) || (ret != *attr))
X509_ATTRIBUTE_free(ret);
return NULL;
}
X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr,
const char *atrname, int type,
const unsigned char *bytes,
int len)
{
ASN1_OBJECT *obj;
X509_ATTRIBUTE *nattr;
obj = OBJ_txt2obj(atrname, 0);
if (obj == NULL) {
X509err(X509_F_X509_ATTRIBUTE_CREATE_BY_TXT,
X509_R_INVALID_FIELD_NAME);
ERR_add_error_data(2, "name=", atrname);
return NULL;
}
nattr = X509_ATTRIBUTE_create_by_OBJ(attr, obj, type, bytes, len);
ASN1_OBJECT_free(obj);
return nattr;
}
int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj)
{
if ((attr == NULL) || (obj == NULL))
return 0;
ASN1_OBJECT_free(attr->object);
attr->object = OBJ_dup(obj);
return attr->object != NULL;
}
int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype,
const void *data, int len)
{
ASN1_TYPE *ttmp = NULL;
ASN1_STRING *stmp = NULL;
int atype = 0;
if (!attr)
return 0;
if (attrtype & MBSTRING_FLAG) {
stmp = ASN1_STRING_set_by_NID(NULL, data, len, attrtype,
OBJ_obj2nid(attr->object));
if (!stmp) {
X509err(X509_F_X509_ATTRIBUTE_SET1_DATA, ERR_R_ASN1_LIB);
return 0;
}
atype = stmp->type;
} else if (len != -1) {
if ((stmp = ASN1_STRING_type_new(attrtype)) == NULL)
goto err;
if (!ASN1_STRING_set(stmp, data, len))
goto err;
atype = attrtype;
}
/*
* This is a bit naughty because the attribute should really have at
* least one value but some types use and zero length SET and require
* this.
*/
if (attrtype == 0) {
ASN1_STRING_free(stmp);
return 1;
}
if ((ttmp = ASN1_TYPE_new()) == NULL)
goto err;
if ((len == -1) && !(attrtype & MBSTRING_FLAG)) {
if (!ASN1_TYPE_set1(ttmp, attrtype, data))
goto err;
} else {
ASN1_TYPE_set(ttmp, atype, stmp);
stmp = NULL;
}
if (!sk_ASN1_TYPE_push(attr->set, ttmp))
goto err;
return 1;
err:
X509err(X509_F_X509_ATTRIBUTE_SET1_DATA, ERR_R_MALLOC_FAILURE);
ASN1_TYPE_free(ttmp);
ASN1_STRING_free(stmp);
return 0;
}
int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *attr)
{
if (attr == NULL)
return 0;
return sk_ASN1_TYPE_num(attr->set);
}
ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr)
{
if (attr == NULL)
return NULL;
return attr->object;
}
void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx,
int atrtype, void *data)
{
ASN1_TYPE *ttmp;
ttmp = X509_ATTRIBUTE_get0_type(attr, idx);
if (!ttmp)
return NULL;
if (atrtype != ASN1_TYPE_get(ttmp)) {
X509err(X509_F_X509_ATTRIBUTE_GET0_DATA, X509_R_WRONG_TYPE);
return NULL;
}
return ttmp->value.ptr;
}
ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx)
{
if (attr == NULL)
return NULL;
return sk_ASN1_TYPE_value(attr->set, idx);
}

View file

@ -0,0 +1,458 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "internal/x509_int.h"
int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b)
{
int i;
const X509_CINF *ai, *bi;
ai = &a->cert_info;
bi = &b->cert_info;
i = ASN1_INTEGER_cmp(&ai->serialNumber, &bi->serialNumber);
if (i)
return i;
return X509_NAME_cmp(ai->issuer, bi->issuer);
}
#ifndef OPENSSL_NO_MD5
unsigned long X509_issuer_and_serial_hash(X509 *a)
{
unsigned long ret = 0;
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
unsigned char md[16];
char *f;
if (ctx == NULL)
goto err;
f = X509_NAME_oneline(a->cert_info.issuer, NULL, 0);
if (!EVP_DigestInit_ex(ctx, EVP_md5(), NULL))
goto err;
if (!EVP_DigestUpdate(ctx, (unsigned char *)f, strlen(f)))
goto err;
OPENSSL_free(f);
if (!EVP_DigestUpdate
(ctx, (unsigned char *)a->cert_info.serialNumber.data,
(unsigned long)a->cert_info.serialNumber.length))
goto err;
if (!EVP_DigestFinal_ex(ctx, &(md[0]), NULL))
goto err;
ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
) & 0xffffffffL;
err:
EVP_MD_CTX_free(ctx);
return ret;
}
#endif
int X509_issuer_name_cmp(const X509 *a, const X509 *b)
{
return X509_NAME_cmp(a->cert_info.issuer, b->cert_info.issuer);
}
int X509_subject_name_cmp(const X509 *a, const X509 *b)
{
return X509_NAME_cmp(a->cert_info.subject, b->cert_info.subject);
}
int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b)
{
return X509_NAME_cmp(a->crl.issuer, b->crl.issuer);
}
int X509_CRL_match(const X509_CRL *a, const X509_CRL *b)
{
return memcmp(a->sha1_hash, b->sha1_hash, 20);
}
X509_NAME *X509_get_issuer_name(const X509 *a)
{
return a->cert_info.issuer;
}
unsigned long X509_issuer_name_hash(X509 *x)
{
return X509_NAME_hash(x->cert_info.issuer);
}
#ifndef OPENSSL_NO_MD5
unsigned long X509_issuer_name_hash_old(X509 *x)
{
return X509_NAME_hash_old(x->cert_info.issuer);
}
#endif
X509_NAME *X509_get_subject_name(const X509 *a)
{
return a->cert_info.subject;
}
ASN1_INTEGER *X509_get_serialNumber(X509 *a)
{
return &a->cert_info.serialNumber;
}
const ASN1_INTEGER *X509_get0_serialNumber(const X509 *a)
{
return &a->cert_info.serialNumber;
}
unsigned long X509_subject_name_hash(X509 *x)
{
return X509_NAME_hash(x->cert_info.subject);
}
#ifndef OPENSSL_NO_MD5
unsigned long X509_subject_name_hash_old(X509 *x)
{
return X509_NAME_hash_old(x->cert_info.subject);
}
#endif
/*
* Compare two certificates: they must be identical for this to work. NB:
* Although "cmp" operations are generally prototyped to take "const"
* arguments (eg. for use in STACKs), the way X509 handling is - these
* operations may involve ensuring the hashes are up-to-date and ensuring
* certain cert information is cached. So this is the point where the
* "depth-first" constification tree has to halt with an evil cast.
*/
int X509_cmp(const X509 *a, const X509 *b)
{
int rv;
/* ensure hash is valid */
X509_check_purpose((X509 *)a, -1, 0);
X509_check_purpose((X509 *)b, -1, 0);
rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
if (rv)
return rv;
/* Check for match against stored encoding too */
if (!a->cert_info.enc.modified && !b->cert_info.enc.modified) {
if (a->cert_info.enc.len < b->cert_info.enc.len)
return -1;
if (a->cert_info.enc.len > b->cert_info.enc.len)
return 1;
return memcmp(a->cert_info.enc.enc, b->cert_info.enc.enc,
a->cert_info.enc.len);
}
return rv;
}
int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b)
{
int ret;
/* Ensure canonical encoding is present and up to date */
if (!a->canon_enc || a->modified) {
ret = i2d_X509_NAME((X509_NAME *)a, NULL);
if (ret < 0)
return -2;
}
if (!b->canon_enc || b->modified) {
ret = i2d_X509_NAME((X509_NAME *)b, NULL);
if (ret < 0)
return -2;
}
ret = a->canon_enclen - b->canon_enclen;
if (ret != 0 || a->canon_enclen == 0)
return ret;
return memcmp(a->canon_enc, b->canon_enc, a->canon_enclen);
}
unsigned long X509_NAME_hash(X509_NAME *x)
{
unsigned long ret = 0;
unsigned char md[SHA_DIGEST_LENGTH];
/* Make sure X509_NAME structure contains valid cached encoding */
i2d_X509_NAME(x, NULL);
if (!EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, EVP_sha1(),
NULL))
return 0;
ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
) & 0xffffffffL;
return ret;
}
#ifndef OPENSSL_NO_MD5
/*
* I now DER encode the name and hash it. Since I cache the DER encoding,
* this is reasonably efficient.
*/
unsigned long X509_NAME_hash_old(X509_NAME *x)
{
EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
unsigned long ret = 0;
unsigned char md[16];
if (md_ctx == NULL)
return ret;
/* Make sure X509_NAME structure contains valid cached encoding */
i2d_X509_NAME(x, NULL);
EVP_MD_CTX_set_flags(md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
if (EVP_DigestInit_ex(md_ctx, EVP_md5(), NULL)
&& EVP_DigestUpdate(md_ctx, x->bytes->data, x->bytes->length)
&& EVP_DigestFinal_ex(md_ctx, md, NULL))
ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
) & 0xffffffffL;
EVP_MD_CTX_free(md_ctx);
return ret;
}
#endif
/* Search a stack of X509 for a match */
X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name,
ASN1_INTEGER *serial)
{
int i;
X509 x, *x509 = NULL;
if (!sk)
return NULL;
x.cert_info.serialNumber = *serial;
x.cert_info.issuer = name;
for (i = 0; i < sk_X509_num(sk); i++) {
x509 = sk_X509_value(sk, i);
if (X509_issuer_and_serial_cmp(x509, &x) == 0)
return x509;
}
return NULL;
}
X509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name)
{
X509 *x509;
int i;
for (i = 0; i < sk_X509_num(sk); i++) {
x509 = sk_X509_value(sk, i);
if (X509_NAME_cmp(X509_get_subject_name(x509), name) == 0)
return x509;
}
return NULL;
}
EVP_PKEY *X509_get0_pubkey(const X509 *x)
{
if (x == NULL)
return NULL;
return X509_PUBKEY_get0(x->cert_info.key);
}
EVP_PKEY *X509_get_pubkey(X509 *x)
{
if (x == NULL)
return NULL;
return X509_PUBKEY_get(x->cert_info.key);
}
int X509_check_private_key(const X509 *x, const EVP_PKEY *k)
{
const EVP_PKEY *xk;
int ret;
xk = X509_get0_pubkey(x);
if (xk)
ret = EVP_PKEY_cmp(xk, k);
else
ret = -2;
switch (ret) {
case 1:
break;
case 0:
X509err(X509_F_X509_CHECK_PRIVATE_KEY, X509_R_KEY_VALUES_MISMATCH);
break;
case -1:
X509err(X509_F_X509_CHECK_PRIVATE_KEY, X509_R_KEY_TYPE_MISMATCH);
break;
case -2:
X509err(X509_F_X509_CHECK_PRIVATE_KEY, X509_R_UNKNOWN_KEY_TYPE);
}
if (ret > 0)
return 1;
return 0;
}
/*
* Check a suite B algorithm is permitted: pass in a public key and the NID
* of its signature (or 0 if no signature). The pflags is a pointer to a
* flags field which must contain the suite B verification flags.
*/
#ifndef OPENSSL_NO_EC
static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags)
{
const EC_GROUP *grp = NULL;
int curve_nid;
if (pkey && EVP_PKEY_id(pkey) == EVP_PKEY_EC)
grp = EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey));
if (!grp)
return X509_V_ERR_SUITE_B_INVALID_ALGORITHM;
curve_nid = EC_GROUP_get_curve_name(grp);
/* Check curve is consistent with LOS */
if (curve_nid == NID_secp384r1) { /* P-384 */
/*
* Check signature algorithm is consistent with curve.
*/
if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA384)
return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
if (!(*pflags & X509_V_FLAG_SUITEB_192_LOS))
return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED;
/* If we encounter P-384 we cannot use P-256 later */
*pflags &= ~X509_V_FLAG_SUITEB_128_LOS_ONLY;
} else if (curve_nid == NID_X9_62_prime256v1) { /* P-256 */
if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA256)
return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
if (!(*pflags & X509_V_FLAG_SUITEB_128_LOS_ONLY))
return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED;
} else
return X509_V_ERR_SUITE_B_INVALID_CURVE;
return X509_V_OK;
}
int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain,
unsigned long flags)
{
int rv, i, sign_nid;
EVP_PKEY *pk;
unsigned long tflags = flags;
if (!(flags & X509_V_FLAG_SUITEB_128_LOS))
return X509_V_OK;
/* If no EE certificate passed in must be first in chain */
if (x == NULL) {
x = sk_X509_value(chain, 0);
i = 1;
} else
i = 0;
pk = X509_get0_pubkey(x);
/*
* With DANE-EE(3) success, or DANE-EE(3)/PKIX-EE(1) failure we don't build
* a chain all, just report trust success or failure, but must also report
* Suite-B errors if applicable. This is indicated via a NULL chain
* pointer. All we need to do is check the leaf key algorithm.
*/
if (chain == NULL)
return check_suite_b(pk, -1, &tflags);
if (X509_get_version(x) != 2) {
rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
/* Correct error depth */
i = 0;
goto end;
}
/* Check EE key only */
rv = check_suite_b(pk, -1, &tflags);
if (rv != X509_V_OK) {
/* Correct error depth */
i = 0;
goto end;
}
for (; i < sk_X509_num(chain); i++) {
sign_nid = X509_get_signature_nid(x);
x = sk_X509_value(chain, i);
if (X509_get_version(x) != 2) {
rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
goto end;
}
pk = X509_get0_pubkey(x);
rv = check_suite_b(pk, sign_nid, &tflags);
if (rv != X509_V_OK)
goto end;
}
/* Final check: root CA signature */
rv = check_suite_b(pk, X509_get_signature_nid(x), &tflags);
end:
if (rv != X509_V_OK) {
/* Invalid signature or LOS errors are for previous cert */
if ((rv == X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM
|| rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED) && i)
i--;
/*
* If we have LOS error and flags changed then we are signing P-384
* with P-256. Use more meaningful error.
*/
if (rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED && flags != tflags)
rv = X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256;
if (perror_depth)
*perror_depth = i;
}
return rv;
}
int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags)
{
int sign_nid;
if (!(flags & X509_V_FLAG_SUITEB_128_LOS))
return X509_V_OK;
sign_nid = OBJ_obj2nid(crl->crl.sig_alg.algorithm);
return check_suite_b(pk, sign_nid, &flags);
}
#else
int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain,
unsigned long flags)
{
return 0;
}
int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags)
{
return 0;
}
#endif
/*
* Not strictly speaking an "up_ref" as a STACK doesn't have a reference
* count but it has the same effect by duping the STACK and upping the ref of
* each X509 structure.
*/
STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain)
{
STACK_OF(X509) *ret;
int i;
ret = sk_X509_dup(chain);
for (i = 0; i < sk_X509_num(ret); i++) {
X509 *x = sk_X509_value(ret, i);
X509_up_ref(x);
}
return ret;
}

View file

@ -0,0 +1,57 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/crypto.h>
#include <openssl/x509.h>
int X509_STORE_set_default_paths(X509_STORE *ctx)
{
X509_LOOKUP *lookup;
lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file());
if (lookup == NULL)
return 0;
X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir());
if (lookup == NULL)
return 0;
X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
/* clear any errors */
ERR_clear_error();
return 1;
}
int X509_STORE_load_locations(X509_STORE *ctx, const char *file,
const char *path)
{
X509_LOOKUP *lookup;
if (file != NULL) {
lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file());
if (lookup == NULL)
return 0;
if (X509_LOOKUP_load_file(lookup, file, X509_FILETYPE_PEM) != 1)
return 0;
}
if (path != NULL) {
lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir());
if (lookup == NULL)
return 0;
if (X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1)
return 0;
}
if ((path == NULL) && (file == NULL))
return 0;
return 1;
}

View file

@ -0,0 +1,43 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/crypto.h>
#include <openssl/x509.h>
const char *X509_get_default_private_dir(void)
{
return X509_PRIVATE_DIR;
}
const char *X509_get_default_cert_area(void)
{
return X509_CERT_AREA;
}
const char *X509_get_default_cert_dir(void)
{
return X509_CERT_DIR;
}
const char *X509_get_default_cert_file(void)
{
return X509_CERT_FILE;
}
const char *X509_get_default_cert_dir_env(void)
{
return X509_CERT_DIR_EVP;
}
const char *X509_get_default_cert_file_env(void)
{
return X509_CERT_FILE_EVP;
}

View file

@ -0,0 +1,181 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/err.h>
#include <openssl/x509err.h>
#ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA X509_str_functs[] = {
{ERR_PACK(ERR_LIB_X509, X509_F_ADD_CERT_DIR, 0), "add_cert_dir"},
{ERR_PACK(ERR_LIB_X509, X509_F_BUILD_CHAIN, 0), "build_chain"},
{ERR_PACK(ERR_LIB_X509, X509_F_BY_FILE_CTRL, 0), "by_file_ctrl"},
{ERR_PACK(ERR_LIB_X509, X509_F_CHECK_NAME_CONSTRAINTS, 0),
"check_name_constraints"},
{ERR_PACK(ERR_LIB_X509, X509_F_CHECK_POLICY, 0), "check_policy"},
{ERR_PACK(ERR_LIB_X509, X509_F_DANE_I2D, 0), "dane_i2d"},
{ERR_PACK(ERR_LIB_X509, X509_F_DIR_CTRL, 0), "dir_ctrl"},
{ERR_PACK(ERR_LIB_X509, X509_F_GET_CERT_BY_SUBJECT, 0),
"get_cert_by_subject"},
{ERR_PACK(ERR_LIB_X509, X509_F_I2D_X509_AUX, 0), "i2d_X509_AUX"},
{ERR_PACK(ERR_LIB_X509, X509_F_LOOKUP_CERTS_SK, 0), "lookup_certs_sk"},
{ERR_PACK(ERR_LIB_X509, X509_F_NETSCAPE_SPKI_B64_DECODE, 0),
"NETSCAPE_SPKI_b64_decode"},
{ERR_PACK(ERR_LIB_X509, X509_F_NETSCAPE_SPKI_B64_ENCODE, 0),
"NETSCAPE_SPKI_b64_encode"},
{ERR_PACK(ERR_LIB_X509, X509_F_NEW_DIR, 0), "new_dir"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509AT_ADD1_ATTR, 0), "X509at_add1_attr"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509V3_ADD_EXT, 0), "X509v3_add_ext"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_CREATE_BY_NID, 0),
"X509_ATTRIBUTE_create_by_NID"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ, 0),
"X509_ATTRIBUTE_create_by_OBJ"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_CREATE_BY_TXT, 0),
"X509_ATTRIBUTE_create_by_txt"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_GET0_DATA, 0),
"X509_ATTRIBUTE_get0_data"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_SET1_DATA, 0),
"X509_ATTRIBUTE_set1_data"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_CHECK_PRIVATE_KEY, 0),
"X509_check_private_key"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_CRL_DIFF, 0), "X509_CRL_diff"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_CRL_METHOD_NEW, 0),
"X509_CRL_METHOD_new"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_CRL_PRINT_FP, 0), "X509_CRL_print_fp"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_EXTENSION_CREATE_BY_NID, 0),
"X509_EXTENSION_create_by_NID"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_EXTENSION_CREATE_BY_OBJ, 0),
"X509_EXTENSION_create_by_OBJ"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_GET_PUBKEY_PARAMETERS, 0),
"X509_get_pubkey_parameters"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_LOAD_CERT_CRL_FILE, 0),
"X509_load_cert_crl_file"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_LOAD_CERT_FILE, 0),
"X509_load_cert_file"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_LOAD_CRL_FILE, 0),
"X509_load_crl_file"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_LOOKUP_METH_NEW, 0),
"X509_LOOKUP_meth_new"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_LOOKUP_NEW, 0), "X509_LOOKUP_new"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ADD_ENTRY, 0),
"X509_NAME_add_entry"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_CANON, 0), "x509_name_canon"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ENTRY_CREATE_BY_NID, 0),
"X509_NAME_ENTRY_create_by_NID"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ENTRY_CREATE_BY_TXT, 0),
"X509_NAME_ENTRY_create_by_txt"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ENTRY_SET_OBJECT, 0),
"X509_NAME_ENTRY_set_object"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ONELINE, 0), "X509_NAME_oneline"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_PRINT, 0), "X509_NAME_print"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_OBJECT_NEW, 0), "X509_OBJECT_new"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_PRINT_EX_FP, 0), "X509_print_ex_fp"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_PUBKEY_DECODE, 0),
"x509_pubkey_decode"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_PUBKEY_GET0, 0), "X509_PUBKEY_get0"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_PUBKEY_SET, 0), "X509_PUBKEY_set"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_CHECK_PRIVATE_KEY, 0),
"X509_REQ_check_private_key"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_PRINT_EX, 0), "X509_REQ_print_ex"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_PRINT_FP, 0), "X509_REQ_print_fp"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_TO_X509, 0), "X509_REQ_to_X509"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_ADD_CERT, 0),
"X509_STORE_add_cert"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_ADD_CRL, 0),
"X509_STORE_add_crl"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_ADD_LOOKUP, 0),
"X509_STORE_add_lookup"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_GET1_ISSUER, 0),
"X509_STORE_CTX_get1_issuer"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_INIT, 0),
"X509_STORE_CTX_init"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_NEW, 0),
"X509_STORE_CTX_new"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_PURPOSE_INHERIT, 0),
"X509_STORE_CTX_purpose_inherit"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_NEW, 0), "X509_STORE_new"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_TO_X509_REQ, 0), "X509_to_X509_REQ"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_TRUST_ADD, 0), "X509_TRUST_add"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_TRUST_SET, 0), "X509_TRUST_set"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_VERIFY_CERT, 0), "X509_verify_cert"},
{ERR_PACK(ERR_LIB_X509, X509_F_X509_VERIFY_PARAM_NEW, 0),
"X509_VERIFY_PARAM_new"},
{0, NULL}
};
static const ERR_STRING_DATA X509_str_reasons[] = {
{ERR_PACK(ERR_LIB_X509, 0, X509_R_AKID_MISMATCH), "akid mismatch"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_BAD_SELECTOR), "bad selector"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_BAD_X509_FILETYPE), "bad x509 filetype"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_BASE64_DECODE_ERROR),
"base64 decode error"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_CANT_CHECK_DH_KEY), "cant check dh key"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_CERT_ALREADY_IN_HASH_TABLE),
"cert already in hash table"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_CRL_ALREADY_DELTA), "crl already delta"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_CRL_VERIFY_FAILURE),
"crl verify failure"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_IDP_MISMATCH), "idp mismatch"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_DIRECTORY), "invalid directory"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_FIELD_NAME),
"invalid field name"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_TRUST), "invalid trust"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_ISSUER_MISMATCH), "issuer mismatch"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_KEY_TYPE_MISMATCH), "key type mismatch"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_KEY_VALUES_MISMATCH),
"key values mismatch"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_LOADING_CERT_DIR), "loading cert dir"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_LOADING_DEFAULTS), "loading defaults"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_METHOD_NOT_SUPPORTED),
"method not supported"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_NAME_TOO_LONG), "name too long"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_NEWER_CRL_NOT_NEWER),
"newer crl not newer"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CERTIFICATE_FOUND),
"no certificate found"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CERTIFICATE_OR_CRL_FOUND),
"no certificate or crl found"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY),
"no cert set for us to verify"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CRL_FOUND), "no crl found"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CRL_NUMBER), "no crl number"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_PUBLIC_KEY_DECODE_ERROR),
"public key decode error"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_PUBLIC_KEY_ENCODE_ERROR),
"public key encode error"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_SHOULD_RETRY), "should retry"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN),
"unable to find parameters in chain"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY),
"unable to get certs public key"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_KEY_TYPE), "unknown key type"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_NID), "unknown nid"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_PURPOSE_ID),
"unknown purpose id"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_TRUST_ID), "unknown trust id"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_UNSUPPORTED_ALGORITHM),
"unsupported algorithm"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_WRONG_LOOKUP_TYPE), "wrong lookup type"},
{ERR_PACK(ERR_LIB_X509, 0, X509_R_WRONG_TYPE), "wrong type"},
{0, NULL}
};
#endif
int ERR_load_X509_strings(void)
{
#ifndef OPENSSL_NO_ERR
if (ERR_func_error_string(X509_str_functs[0].error) == NULL) {
ERR_load_strings_const(X509_str_functs);
ERR_load_strings_const(X509_str_reasons);
}
#endif
return 1;
}

View file

@ -0,0 +1,159 @@
/*
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include "internal/x509_int.h"
#include <openssl/x509v3.h>
int X509_CRL_get_ext_count(const X509_CRL *x)
{
return X509v3_get_ext_count(x->crl.extensions);
}
int X509_CRL_get_ext_by_NID(const X509_CRL *x, int nid, int lastpos)
{
return X509v3_get_ext_by_NID(x->crl.extensions, nid, lastpos);
}
int X509_CRL_get_ext_by_OBJ(const X509_CRL *x, const ASN1_OBJECT *obj,
int lastpos)
{
return X509v3_get_ext_by_OBJ(x->crl.extensions, obj, lastpos);
}
int X509_CRL_get_ext_by_critical(const X509_CRL *x, int crit, int lastpos)
{
return X509v3_get_ext_by_critical(x->crl.extensions, crit, lastpos);
}
X509_EXTENSION *X509_CRL_get_ext(const X509_CRL *x, int loc)
{
return X509v3_get_ext(x->crl.extensions, loc);
}
X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc)
{
return X509v3_delete_ext(x->crl.extensions, loc);
}
void *X509_CRL_get_ext_d2i(const X509_CRL *x, int nid, int *crit, int *idx)
{
return X509V3_get_d2i(x->crl.extensions, nid, crit, idx);
}
int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit,
unsigned long flags)
{
return X509V3_add1_i2d(&x->crl.extensions, nid, value, crit, flags);
}
int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc)
{
return (X509v3_add_ext(&(x->crl.extensions), ex, loc) != NULL);
}
int X509_get_ext_count(const X509 *x)
{
return X509v3_get_ext_count(x->cert_info.extensions);
}
int X509_get_ext_by_NID(const X509 *x, int nid, int lastpos)
{
return X509v3_get_ext_by_NID(x->cert_info.extensions, nid, lastpos);
}
int X509_get_ext_by_OBJ(const X509 *x, const ASN1_OBJECT *obj, int lastpos)
{
return X509v3_get_ext_by_OBJ(x->cert_info.extensions, obj, lastpos);
}
int X509_get_ext_by_critical(const X509 *x, int crit, int lastpos)
{
return (X509v3_get_ext_by_critical
(x->cert_info.extensions, crit, lastpos));
}
X509_EXTENSION *X509_get_ext(const X509 *x, int loc)
{
return X509v3_get_ext(x->cert_info.extensions, loc);
}
X509_EXTENSION *X509_delete_ext(X509 *x, int loc)
{
return X509v3_delete_ext(x->cert_info.extensions, loc);
}
int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc)
{
return (X509v3_add_ext(&(x->cert_info.extensions), ex, loc) != NULL);
}
void *X509_get_ext_d2i(const X509 *x, int nid, int *crit, int *idx)
{
return X509V3_get_d2i(x->cert_info.extensions, nid, crit, idx);
}
int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit,
unsigned long flags)
{
return X509V3_add1_i2d(&x->cert_info.extensions, nid, value, crit,
flags);
}
int X509_REVOKED_get_ext_count(const X509_REVOKED *x)
{
return X509v3_get_ext_count(x->extensions);
}
int X509_REVOKED_get_ext_by_NID(const X509_REVOKED *x, int nid, int lastpos)
{
return X509v3_get_ext_by_NID(x->extensions, nid, lastpos);
}
int X509_REVOKED_get_ext_by_OBJ(const X509_REVOKED *x, const ASN1_OBJECT *obj,
int lastpos)
{
return X509v3_get_ext_by_OBJ(x->extensions, obj, lastpos);
}
int X509_REVOKED_get_ext_by_critical(const X509_REVOKED *x, int crit, int lastpos)
{
return X509v3_get_ext_by_critical(x->extensions, crit, lastpos);
}
X509_EXTENSION *X509_REVOKED_get_ext(const X509_REVOKED *x, int loc)
{
return X509v3_get_ext(x->extensions, loc);
}
X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc)
{
return X509v3_delete_ext(x->extensions, loc);
}
int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc)
{
return (X509v3_add_ext(&(x->extensions), ex, loc) != NULL);
}
void *X509_REVOKED_get_ext_d2i(const X509_REVOKED *x, int nid, int *crit, int *idx)
{
return X509V3_get_d2i(x->extensions, nid, crit, idx);
}
int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit,
unsigned long flags)
{
return X509V3_add1_i2d(&x->extensions, nid, value, crit, flags);
}

View file

@ -0,0 +1,147 @@
/*
* Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "internal/refcount.h"
/*
* This structure holds all parameters associated with a verify operation by
* including an X509_VERIFY_PARAM structure in related structures the
* parameters used can be customized
*/
struct X509_VERIFY_PARAM_st {
char *name;
time_t check_time; /* Time to use */
uint32_t inh_flags; /* Inheritance flags */
unsigned long flags; /* Various verify flags */
int purpose; /* purpose to check untrusted certificates */
int trust; /* trust setting to check */
int depth; /* Verify depth */
int auth_level; /* Security level for chain verification */
STACK_OF(ASN1_OBJECT) *policies; /* Permissible policies */
/* Peer identity details */
STACK_OF(OPENSSL_STRING) *hosts; /* Set of acceptable names */
unsigned int hostflags; /* Flags to control matching features */
char *peername; /* Matching hostname in peer certificate */
char *email; /* If not NULL email address to match */
size_t emaillen;
unsigned char *ip; /* If not NULL IP address to match */
size_t iplen; /* Length of IP address */
};
/* No error callback if depth < 0 */
int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth);
/* a sequence of these are used */
struct x509_attributes_st {
ASN1_OBJECT *object;
STACK_OF(ASN1_TYPE) *set;
};
struct X509_extension_st {
ASN1_OBJECT *object;
ASN1_BOOLEAN critical;
ASN1_OCTET_STRING value;
};
/*
* Method to handle CRL access. In general a CRL could be very large (several
* Mb) and can consume large amounts of resources if stored in memory by
* multiple processes. This method allows general CRL operations to be
* redirected to more efficient callbacks: for example a CRL entry database.
*/
#define X509_CRL_METHOD_DYNAMIC 1
struct x509_crl_method_st {
int flags;
int (*crl_init) (X509_CRL *crl);
int (*crl_free) (X509_CRL *crl);
int (*crl_lookup) (X509_CRL *crl, X509_REVOKED **ret,
ASN1_INTEGER *ser, X509_NAME *issuer);
int (*crl_verify) (X509_CRL *crl, EVP_PKEY *pk);
};
struct x509_lookup_method_st {
char *name;
int (*new_item) (X509_LOOKUP *ctx);
void (*free) (X509_LOOKUP *ctx);
int (*init) (X509_LOOKUP *ctx);
int (*shutdown) (X509_LOOKUP *ctx);
int (*ctrl) (X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
char **ret);
int (*get_by_subject) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
X509_NAME *name, X509_OBJECT *ret);
int (*get_by_issuer_serial) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
X509_NAME *name, ASN1_INTEGER *serial,
X509_OBJECT *ret);
int (*get_by_fingerprint) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
const unsigned char *bytes, int len,
X509_OBJECT *ret);
int (*get_by_alias) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
const char *str, int len, X509_OBJECT *ret);
};
/* This is the functions plus an instance of the local variables. */
struct x509_lookup_st {
int init; /* have we been started */
int skip; /* don't use us. */
X509_LOOKUP_METHOD *method; /* the functions */
void *method_data; /* method data */
X509_STORE *store_ctx; /* who owns us */
};
/*
* This is used to hold everything. It is used for all certificate
* validation. Once we have a certificate chain, the 'verify' function is
* then called to actually check the cert chain.
*/
struct x509_store_st {
/* The following is a cache of trusted certs */
int cache; /* if true, stash any hits */
STACK_OF(X509_OBJECT) *objs; /* Cache of all objects */
/* These are external lookup methods */
STACK_OF(X509_LOOKUP) *get_cert_methods;
X509_VERIFY_PARAM *param;
/* Callbacks for various operations */
/* called to verify a certificate */
int (*verify) (X509_STORE_CTX *ctx);
/* error callback */
int (*verify_cb) (int ok, X509_STORE_CTX *ctx);
/* get issuers cert from ctx */
int (*get_issuer) (X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
/* check issued */
int (*check_issued) (X509_STORE_CTX *ctx, X509 *x, X509 *issuer);
/* Check revocation status of chain */
int (*check_revocation) (X509_STORE_CTX *ctx);
/* retrieve CRL */
int (*get_crl) (X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x);
/* Check CRL validity */
int (*check_crl) (X509_STORE_CTX *ctx, X509_CRL *crl);
/* Check certificate against CRL */
int (*cert_crl) (X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x);
/* Check policy status of the chain */
int (*check_policy) (X509_STORE_CTX *ctx);
STACK_OF(X509) *(*lookup_certs) (X509_STORE_CTX *ctx, X509_NAME *nm);
STACK_OF(X509_CRL) *(*lookup_crls) (X509_STORE_CTX *ctx, X509_NAME *nm);
int (*cleanup) (X509_STORE_CTX *ctx);
CRYPTO_EX_DATA ex_data;
CRYPTO_REF_COUNT references;
CRYPTO_RWLOCK *lock;
};
typedef struct lookup_dir_hashes_st BY_DIR_HASH;
typedef struct lookup_dir_entry_st BY_DIR_ENTRY;
DEFINE_STACK_OF(BY_DIR_HASH)
DEFINE_STACK_OF(BY_DIR_ENTRY)
typedef STACK_OF(X509_NAME_ENTRY) STACK_OF_X509_NAME_ENTRY;
DEFINE_STACK_OF(STACK_OF_X509_NAME_ENTRY)
void x509_set_signature_info(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
const ASN1_STRING *sig);

View file

@ -0,0 +1,898 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include "internal/refcount.h"
#include <openssl/x509.h>
#include "internal/x509_int.h"
#include <openssl/x509v3.h>
#include "x509_lcl.h"
X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
{
X509_LOOKUP *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
X509err(X509_F_X509_LOOKUP_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->method = method;
if (method->new_item != NULL && method->new_item(ret) == 0) {
OPENSSL_free(ret);
return NULL;
}
return ret;
}
void X509_LOOKUP_free(X509_LOOKUP *ctx)
{
if (ctx == NULL)
return;
if ((ctx->method != NULL) && (ctx->method->free != NULL))
(*ctx->method->free) (ctx);
OPENSSL_free(ctx);
}
int X509_STORE_lock(X509_STORE *s)
{
return CRYPTO_THREAD_write_lock(s->lock);
}
int X509_STORE_unlock(X509_STORE *s)
{
return CRYPTO_THREAD_unlock(s->lock);
}
int X509_LOOKUP_init(X509_LOOKUP *ctx)
{
if (ctx->method == NULL)
return 0;
if (ctx->method->init != NULL)
return ctx->method->init(ctx);
else
return 1;
}
int X509_LOOKUP_shutdown(X509_LOOKUP *ctx)
{
if (ctx->method == NULL)
return 0;
if (ctx->method->shutdown != NULL)
return ctx->method->shutdown(ctx);
else
return 1;
}
int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
char **ret)
{
if (ctx->method == NULL)
return -1;
if (ctx->method->ctrl != NULL)
return ctx->method->ctrl(ctx, cmd, argc, argl, ret);
else
return 1;
}
int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
X509_NAME *name, X509_OBJECT *ret)
{
if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL))
return 0;
if (ctx->skip)
return 0;
return ctx->method->get_by_subject(ctx, type, name, ret);
}
int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
X509_NAME *name, ASN1_INTEGER *serial,
X509_OBJECT *ret)
{
if ((ctx->method == NULL) || (ctx->method->get_by_issuer_serial == NULL))
return 0;
return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret);
}
int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
const unsigned char *bytes, int len,
X509_OBJECT *ret)
{
if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL))
return 0;
return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret);
}
int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
const char *str, int len, X509_OBJECT *ret)
{
if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL))
return 0;
return ctx->method->get_by_alias(ctx, type, str, len, ret);
}
int X509_LOOKUP_set_method_data(X509_LOOKUP *ctx, void *data)
{
ctx->method_data = data;
return 1;
}
void *X509_LOOKUP_get_method_data(const X509_LOOKUP *ctx)
{
return ctx->method_data;
}
X509_STORE *X509_LOOKUP_get_store(const X509_LOOKUP *ctx)
{
return ctx->store_ctx;
}
static int x509_object_cmp(const X509_OBJECT *const *a,
const X509_OBJECT *const *b)
{
int ret;
ret = ((*a)->type - (*b)->type);
if (ret)
return ret;
switch ((*a)->type) {
case X509_LU_X509:
ret = X509_subject_name_cmp((*a)->data.x509, (*b)->data.x509);
break;
case X509_LU_CRL:
ret = X509_CRL_cmp((*a)->data.crl, (*b)->data.crl);
break;
case X509_LU_NONE:
/* abort(); */
return 0;
}
return ret;
}
X509_STORE *X509_STORE_new(void)
{
X509_STORE *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
if ((ret->objs = sk_X509_OBJECT_new(x509_object_cmp)) == NULL) {
X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
goto err;
}
ret->cache = 1;
if ((ret->get_cert_methods = sk_X509_LOOKUP_new_null()) == NULL) {
X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
goto err;
}
if ((ret->param = X509_VERIFY_PARAM_new()) == NULL) {
X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data)) {
X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
goto err;
}
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
goto err;
}
ret->references = 1;
return ret;
err:
X509_VERIFY_PARAM_free(ret->param);
sk_X509_OBJECT_free(ret->objs);
sk_X509_LOOKUP_free(ret->get_cert_methods);
OPENSSL_free(ret);
return NULL;
}
void X509_STORE_free(X509_STORE *vfy)
{
int i;
STACK_OF(X509_LOOKUP) *sk;
X509_LOOKUP *lu;
if (vfy == NULL)
return;
CRYPTO_DOWN_REF(&vfy->references, &i, vfy->lock);
REF_PRINT_COUNT("X509_STORE", vfy);
if (i > 0)
return;
REF_ASSERT_ISNT(i < 0);
sk = vfy->get_cert_methods;
for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) {
lu = sk_X509_LOOKUP_value(sk, i);
X509_LOOKUP_shutdown(lu);
X509_LOOKUP_free(lu);
}
sk_X509_LOOKUP_free(sk);
sk_X509_OBJECT_pop_free(vfy->objs, X509_OBJECT_free);
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, vfy, &vfy->ex_data);
X509_VERIFY_PARAM_free(vfy->param);
CRYPTO_THREAD_lock_free(vfy->lock);
OPENSSL_free(vfy);
}
int X509_STORE_up_ref(X509_STORE *vfy)
{
int i;
if (CRYPTO_UP_REF(&vfy->references, &i, vfy->lock) <= 0)
return 0;
REF_PRINT_COUNT("X509_STORE", a);
REF_ASSERT_ISNT(i < 2);
return ((i > 1) ? 1 : 0);
}
X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m)
{
int i;
STACK_OF(X509_LOOKUP) *sk;
X509_LOOKUP *lu;
sk = v->get_cert_methods;
for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) {
lu = sk_X509_LOOKUP_value(sk, i);
if (m == lu->method) {
return lu;
}
}
/* a new one */
lu = X509_LOOKUP_new(m);
if (lu == NULL) {
X509err(X509_F_X509_STORE_ADD_LOOKUP, ERR_R_MALLOC_FAILURE);
return NULL;
}
lu->store_ctx = v;
if (sk_X509_LOOKUP_push(v->get_cert_methods, lu))
return lu;
/* malloc failed */
X509err(X509_F_X509_STORE_ADD_LOOKUP, ERR_R_MALLOC_FAILURE);
X509_LOOKUP_free(lu);
return NULL;
}
X509_OBJECT *X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs,
X509_LOOKUP_TYPE type,
X509_NAME *name)
{
X509_OBJECT *ret = X509_OBJECT_new();
if (ret == NULL)
return NULL;
if (!X509_STORE_CTX_get_by_subject(vs, type, name, ret)) {
X509_OBJECT_free(ret);
return NULL;
}
return ret;
}
int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type,
X509_NAME *name, X509_OBJECT *ret)
{
X509_STORE *ctx = vs->ctx;
X509_LOOKUP *lu;
X509_OBJECT stmp, *tmp;
int i, j;
if (ctx == NULL)
return 0;
CRYPTO_THREAD_write_lock(ctx->lock);
tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name);
CRYPTO_THREAD_unlock(ctx->lock);
if (tmp == NULL || type == X509_LU_CRL) {
for (i = 0; i < sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) {
lu = sk_X509_LOOKUP_value(ctx->get_cert_methods, i);
j = X509_LOOKUP_by_subject(lu, type, name, &stmp);
if (j) {
tmp = &stmp;
break;
}
}
if (tmp == NULL)
return 0;
}
ret->type = tmp->type;
ret->data.ptr = tmp->data.ptr;
X509_OBJECT_up_ref_count(ret);
return 1;
}
static int x509_store_add(X509_STORE *ctx, void *x, int crl) {
X509_OBJECT *obj;
int ret = 0, added = 0;
if (x == NULL)
return 0;
obj = X509_OBJECT_new();
if (obj == NULL)
return 0;
if (crl) {
obj->type = X509_LU_CRL;
obj->data.crl = (X509_CRL *)x;
} else {
obj->type = X509_LU_X509;
obj->data.x509 = (X509 *)x;
}
X509_OBJECT_up_ref_count(obj);
CRYPTO_THREAD_write_lock(ctx->lock);
if (X509_OBJECT_retrieve_match(ctx->objs, obj)) {
ret = 1;
} else {
added = sk_X509_OBJECT_push(ctx->objs, obj);
ret = added != 0;
}
CRYPTO_THREAD_unlock(ctx->lock);
if (added == 0) /* obj not pushed */
X509_OBJECT_free(obj);
return ret;
}
int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
{
if (!x509_store_add(ctx, x, 0)) {
X509err(X509_F_X509_STORE_ADD_CERT, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
}
int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
{
if (!x509_store_add(ctx, x, 1)) {
X509err(X509_F_X509_STORE_ADD_CRL, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
}
int X509_OBJECT_up_ref_count(X509_OBJECT *a)
{
switch (a->type) {
case X509_LU_NONE:
break;
case X509_LU_X509:
return X509_up_ref(a->data.x509);
case X509_LU_CRL:
return X509_CRL_up_ref(a->data.crl);
}
return 1;
}
X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a)
{
if (a == NULL || a->type != X509_LU_X509)
return NULL;
return a->data.x509;
}
X509_CRL *X509_OBJECT_get0_X509_CRL(X509_OBJECT *a)
{
if (a == NULL || a->type != X509_LU_CRL)
return NULL;
return a->data.crl;
}
X509_LOOKUP_TYPE X509_OBJECT_get_type(const X509_OBJECT *a)
{
return a->type;
}
X509_OBJECT *X509_OBJECT_new(void)
{
X509_OBJECT *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
X509err(X509_F_X509_OBJECT_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->type = X509_LU_NONE;
return ret;
}
static void x509_object_free_internal(X509_OBJECT *a)
{
if (a == NULL)
return;
switch (a->type) {
case X509_LU_NONE:
break;
case X509_LU_X509:
X509_free(a->data.x509);
break;
case X509_LU_CRL:
X509_CRL_free(a->data.crl);
break;
}
}
int X509_OBJECT_set1_X509(X509_OBJECT *a, X509 *obj)
{
if (a == NULL || !X509_up_ref(obj))
return 0;
x509_object_free_internal(a);
a->type = X509_LU_X509;
a->data.x509 = obj;
return 1;
}
int X509_OBJECT_set1_X509_CRL(X509_OBJECT *a, X509_CRL *obj)
{
if (a == NULL || !X509_CRL_up_ref(obj))
return 0;
x509_object_free_internal(a);
a->type = X509_LU_CRL;
a->data.crl = obj;
return 1;
}
void X509_OBJECT_free(X509_OBJECT *a)
{
x509_object_free_internal(a);
OPENSSL_free(a);
}
static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
X509_NAME *name, int *pnmatch)
{
X509_OBJECT stmp;
X509 x509_s;
X509_CRL crl_s;
int idx;
stmp.type = type;
switch (type) {
case X509_LU_X509:
stmp.data.x509 = &x509_s;
x509_s.cert_info.subject = name;
break;
case X509_LU_CRL:
stmp.data.crl = &crl_s;
crl_s.crl.issuer = name;
break;
case X509_LU_NONE:
/* abort(); */
return -1;
}
idx = sk_X509_OBJECT_find(h, &stmp);
if (idx >= 0 && pnmatch) {
int tidx;
const X509_OBJECT *tobj, *pstmp;
*pnmatch = 1;
pstmp = &stmp;
for (tidx = idx + 1; tidx < sk_X509_OBJECT_num(h); tidx++) {
tobj = sk_X509_OBJECT_value(h, tidx);
if (x509_object_cmp(&tobj, &pstmp))
break;
(*pnmatch)++;
}
}
return idx;
}
int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
X509_NAME *name)
{
return x509_object_idx_cnt(h, type, name, NULL);
}
X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,
X509_LOOKUP_TYPE type,
X509_NAME *name)
{
int idx;
idx = X509_OBJECT_idx_by_subject(h, type, name);
if (idx == -1)
return NULL;
return sk_X509_OBJECT_value(h, idx);
}
STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *v)
{
return v->objs;
}
STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
{
int i, idx, cnt;
STACK_OF(X509) *sk = NULL;
X509 *x;
X509_OBJECT *obj;
if (ctx->ctx == NULL)
return NULL;
CRYPTO_THREAD_write_lock(ctx->ctx->lock);
idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
if (idx < 0) {
/*
* Nothing found in cache: do lookup to possibly add new objects to
* cache
*/
X509_OBJECT *xobj = X509_OBJECT_new();
CRYPTO_THREAD_unlock(ctx->ctx->lock);
if (xobj == NULL)
return NULL;
if (!X509_STORE_CTX_get_by_subject(ctx, X509_LU_X509, nm, xobj)) {
X509_OBJECT_free(xobj);
return NULL;
}
X509_OBJECT_free(xobj);
CRYPTO_THREAD_write_lock(ctx->ctx->lock);
idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
if (idx < 0) {
CRYPTO_THREAD_unlock(ctx->ctx->lock);
return NULL;
}
}
sk = sk_X509_new_null();
for (i = 0; i < cnt; i++, idx++) {
obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
x = obj->data.x509;
X509_up_ref(x);
if (!sk_X509_push(sk, x)) {
CRYPTO_THREAD_unlock(ctx->ctx->lock);
X509_free(x);
sk_X509_pop_free(sk, X509_free);
return NULL;
}
}
CRYPTO_THREAD_unlock(ctx->ctx->lock);
return sk;
}
STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
{
int i, idx, cnt;
STACK_OF(X509_CRL) *sk = sk_X509_CRL_new_null();
X509_CRL *x;
X509_OBJECT *obj, *xobj = X509_OBJECT_new();
/* Always do lookup to possibly add new CRLs to cache */
if (sk == NULL
|| xobj == NULL
|| ctx->ctx == NULL
|| !X509_STORE_CTX_get_by_subject(ctx, X509_LU_CRL, nm, xobj)) {
X509_OBJECT_free(xobj);
sk_X509_CRL_free(sk);
return NULL;
}
X509_OBJECT_free(xobj);
CRYPTO_THREAD_write_lock(ctx->ctx->lock);
idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt);
if (idx < 0) {
CRYPTO_THREAD_unlock(ctx->ctx->lock);
sk_X509_CRL_free(sk);
return NULL;
}
for (i = 0; i < cnt; i++, idx++) {
obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
x = obj->data.crl;
X509_CRL_up_ref(x);
if (!sk_X509_CRL_push(sk, x)) {
CRYPTO_THREAD_unlock(ctx->ctx->lock);
X509_CRL_free(x);
sk_X509_CRL_pop_free(sk, X509_CRL_free);
return NULL;
}
}
CRYPTO_THREAD_unlock(ctx->ctx->lock);
return sk;
}
X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
X509_OBJECT *x)
{
int idx, i, num;
X509_OBJECT *obj;
idx = sk_X509_OBJECT_find(h, x);
if (idx < 0)
return NULL;
if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL))
return sk_X509_OBJECT_value(h, idx);
for (i = idx, num = sk_X509_OBJECT_num(h); i < num; i++) {
obj = sk_X509_OBJECT_value(h, i);
if (x509_object_cmp((const X509_OBJECT **)&obj,
(const X509_OBJECT **)&x))
return NULL;
if (x->type == X509_LU_X509) {
if (!X509_cmp(obj->data.x509, x->data.x509))
return obj;
} else if (x->type == X509_LU_CRL) {
if (!X509_CRL_match(obj->data.crl, x->data.crl))
return obj;
} else
return obj;
}
return NULL;
}
/*-
* Try to get issuer certificate from store. Due to limitations
* of the API this can only retrieve a single certificate matching
* a given subject name. However it will fill the cache with all
* matching certificates, so we can examine the cache for all
* matches.
*
* Return values are:
* 1 lookup successful.
* 0 certificate not found.
* -1 some other error.
*/
int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
{
X509_NAME *xn;
X509_OBJECT *obj = X509_OBJECT_new(), *pobj = NULL;
int i, ok, idx, ret;
if (obj == NULL)
return -1;
*issuer = NULL;
xn = X509_get_issuer_name(x);
ok = X509_STORE_CTX_get_by_subject(ctx, X509_LU_X509, xn, obj);
if (ok != 1) {
X509_OBJECT_free(obj);
return 0;
}
/* If certificate matches all OK */
if (ctx->check_issued(ctx, x, obj->data.x509)) {
if (x509_check_cert_time(ctx, obj->data.x509, -1)) {
*issuer = obj->data.x509;
X509_up_ref(*issuer);
X509_OBJECT_free(obj);
return 1;
}
}
X509_OBJECT_free(obj);
if (ctx->ctx == NULL)
return 0;
/* Else find index of first cert accepted by 'check_issued' */
ret = 0;
CRYPTO_THREAD_write_lock(ctx->ctx->lock);
idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn);
if (idx != -1) { /* should be true as we've had at least one
* match */
/* Look through all matching certs for suitable issuer */
for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++) {
pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i);
/* See if we've run past the matches */
if (pobj->type != X509_LU_X509)
break;
if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509)))
break;
if (ctx->check_issued(ctx, x, pobj->data.x509)) {
*issuer = pobj->data.x509;
ret = 1;
/*
* If times check, exit with match,
* otherwise keep looking. Leave last
* match in issuer so we return nearest
* match if no certificate time is OK.
*/
if (x509_check_cert_time(ctx, *issuer, -1))
break;
}
}
}
CRYPTO_THREAD_unlock(ctx->ctx->lock);
if (*issuer)
X509_up_ref(*issuer);
return ret;
}
int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags)
{
return X509_VERIFY_PARAM_set_flags(ctx->param, flags);
}
int X509_STORE_set_depth(X509_STORE *ctx, int depth)
{
X509_VERIFY_PARAM_set_depth(ctx->param, depth);
return 1;
}
int X509_STORE_set_purpose(X509_STORE *ctx, int purpose)
{
return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
}
int X509_STORE_set_trust(X509_STORE *ctx, int trust)
{
return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
}
int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param)
{
return X509_VERIFY_PARAM_set1(ctx->param, param);
}
X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx)
{
return ctx->param;
}
void X509_STORE_set_verify(X509_STORE *ctx, X509_STORE_CTX_verify_fn verify)
{
ctx->verify = verify;
}
X509_STORE_CTX_verify_fn X509_STORE_get_verify(X509_STORE *ctx)
{
return ctx->verify;
}
void X509_STORE_set_verify_cb(X509_STORE *ctx,
X509_STORE_CTX_verify_cb verify_cb)
{
ctx->verify_cb = verify_cb;
}
X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(X509_STORE *ctx)
{
return ctx->verify_cb;
}
void X509_STORE_set_get_issuer(X509_STORE *ctx,
X509_STORE_CTX_get_issuer_fn get_issuer)
{
ctx->get_issuer = get_issuer;
}
X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(X509_STORE *ctx)
{
return ctx->get_issuer;
}
void X509_STORE_set_check_issued(X509_STORE *ctx,
X509_STORE_CTX_check_issued_fn check_issued)
{
ctx->check_issued = check_issued;
}
X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(X509_STORE *ctx)
{
return ctx->check_issued;
}
void X509_STORE_set_check_revocation(X509_STORE *ctx,
X509_STORE_CTX_check_revocation_fn check_revocation)
{
ctx->check_revocation = check_revocation;
}
X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation(X509_STORE *ctx)
{
return ctx->check_revocation;
}
void X509_STORE_set_get_crl(X509_STORE *ctx,
X509_STORE_CTX_get_crl_fn get_crl)
{
ctx->get_crl = get_crl;
}
X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(X509_STORE *ctx)
{
return ctx->get_crl;
}
void X509_STORE_set_check_crl(X509_STORE *ctx,
X509_STORE_CTX_check_crl_fn check_crl)
{
ctx->check_crl = check_crl;
}
X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(X509_STORE *ctx)
{
return ctx->check_crl;
}
void X509_STORE_set_cert_crl(X509_STORE *ctx,
X509_STORE_CTX_cert_crl_fn cert_crl)
{
ctx->cert_crl = cert_crl;
}
X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(X509_STORE *ctx)
{
return ctx->cert_crl;
}
void X509_STORE_set_check_policy(X509_STORE *ctx,
X509_STORE_CTX_check_policy_fn check_policy)
{
ctx->check_policy = check_policy;
}
X509_STORE_CTX_check_policy_fn X509_STORE_get_check_policy(X509_STORE *ctx)
{
return ctx->check_policy;
}
void X509_STORE_set_lookup_certs(X509_STORE *ctx,
X509_STORE_CTX_lookup_certs_fn lookup_certs)
{
ctx->lookup_certs = lookup_certs;
}
X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(X509_STORE *ctx)
{
return ctx->lookup_certs;
}
void X509_STORE_set_lookup_crls(X509_STORE *ctx,
X509_STORE_CTX_lookup_crls_fn lookup_crls)
{
ctx->lookup_crls = lookup_crls;
}
X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(X509_STORE *ctx)
{
return ctx->lookup_crls;
}
void X509_STORE_set_cleanup(X509_STORE *ctx,
X509_STORE_CTX_cleanup_fn ctx_cleanup)
{
ctx->cleanup = ctx_cleanup;
}
X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(X509_STORE *ctx)
{
return ctx->cleanup;
}
int X509_STORE_set_ex_data(X509_STORE *ctx, int idx, void *data)
{
return CRYPTO_set_ex_data(&ctx->ex_data, idx, data);
}
void *X509_STORE_get_ex_data(X509_STORE *ctx, int idx)
{
return CRYPTO_get_ex_data(&ctx->ex_data, idx);
}
X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx)
{
return ctx->ctx;
}

View file

@ -0,0 +1,166 @@
/*
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
#include <openssl/x509.h>
#include <openssl/ossl_typ.h>
#include "x509_lcl.h"
X509_LOOKUP_METHOD *X509_LOOKUP_meth_new(const char *name)
{
X509_LOOKUP_METHOD *method = OPENSSL_zalloc(sizeof(X509_LOOKUP_METHOD));
if (method != NULL) {
method->name = OPENSSL_strdup(name);
if (method->name == NULL) {
X509err(X509_F_X509_LOOKUP_METH_NEW, ERR_R_MALLOC_FAILURE);
goto err;
}
}
return method;
err:
OPENSSL_free(method);
return NULL;
}
void X509_LOOKUP_meth_free(X509_LOOKUP_METHOD *method)
{
if (method != NULL)
OPENSSL_free(method->name);
OPENSSL_free(method);
}
int X509_LOOKUP_meth_set_new_item(X509_LOOKUP_METHOD *method,
int (*new_item) (X509_LOOKUP *ctx))
{
method->new_item = new_item;
return 1;
}
int (*X509_LOOKUP_meth_get_new_item(const X509_LOOKUP_METHOD* method))
(X509_LOOKUP *ctx)
{
return method->new_item;
}
int X509_LOOKUP_meth_set_free(
X509_LOOKUP_METHOD *method,
void (*free_fn) (X509_LOOKUP *ctx))
{
method->free = free_fn;
return 1;
}
void (*X509_LOOKUP_meth_get_free(const X509_LOOKUP_METHOD* method))
(X509_LOOKUP *ctx)
{
return method->free;
}
int X509_LOOKUP_meth_set_init(X509_LOOKUP_METHOD *method,
int (*init) (X509_LOOKUP *ctx))
{
method->init = init;
return 1;
}
int (*X509_LOOKUP_meth_get_init(const X509_LOOKUP_METHOD* method))
(X509_LOOKUP *ctx)
{
return method->init;
}
int X509_LOOKUP_meth_set_shutdown(
X509_LOOKUP_METHOD *method,
int (*shutdown) (X509_LOOKUP *ctx))
{
method->shutdown = shutdown;
return 1;
}
int (*X509_LOOKUP_meth_get_shutdown(const X509_LOOKUP_METHOD* method))
(X509_LOOKUP *ctx)
{
return method->shutdown;
}
int X509_LOOKUP_meth_set_ctrl(
X509_LOOKUP_METHOD *method,
X509_LOOKUP_ctrl_fn ctrl)
{
method->ctrl = ctrl;
return 1;
}
X509_LOOKUP_ctrl_fn X509_LOOKUP_meth_get_ctrl(const X509_LOOKUP_METHOD *method)
{
return method->ctrl;
}
int X509_LOOKUP_meth_set_get_by_subject(X509_LOOKUP_METHOD *method,
X509_LOOKUP_get_by_subject_fn get_by_subject)
{
method->get_by_subject = get_by_subject;
return 1;
}
X509_LOOKUP_get_by_subject_fn X509_LOOKUP_meth_get_get_by_subject(
const X509_LOOKUP_METHOD *method)
{
return method->get_by_subject;
}
int X509_LOOKUP_meth_set_get_by_issuer_serial(X509_LOOKUP_METHOD *method,
X509_LOOKUP_get_by_issuer_serial_fn get_by_issuer_serial)
{
method->get_by_issuer_serial = get_by_issuer_serial;
return 1;
}
X509_LOOKUP_get_by_issuer_serial_fn
X509_LOOKUP_meth_get_get_by_issuer_serial(const X509_LOOKUP_METHOD *method)
{
return method->get_by_issuer_serial;
}
int X509_LOOKUP_meth_set_get_by_fingerprint(X509_LOOKUP_METHOD *method,
X509_LOOKUP_get_by_fingerprint_fn get_by_fingerprint)
{
method->get_by_fingerprint = get_by_fingerprint;
return 1;
}
X509_LOOKUP_get_by_fingerprint_fn X509_LOOKUP_meth_get_get_by_fingerprint(
const X509_LOOKUP_METHOD *method)
{
return method->get_by_fingerprint;
}
int X509_LOOKUP_meth_set_get_by_alias(X509_LOOKUP_METHOD *method,
X509_LOOKUP_get_by_alias_fn get_by_alias)
{
method->get_by_alias = get_by_alias;
return 1;
}
X509_LOOKUP_get_by_alias_fn X509_LOOKUP_meth_get_get_by_alias(
const X509_LOOKUP_METHOD *method)
{
return method->get_by_alias;
}

View file

@ -0,0 +1,181 @@
/*
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/buffer.h>
#include "internal/x509_int.h"
/*
* Limit to ensure we don't overflow: much greater than
* anything encountered in practice.
*/
#define NAME_ONELINE_MAX (1024 * 1024)
char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len)
{
const X509_NAME_ENTRY *ne;
int i;
int n, lold, l, l1, l2, num, j, type;
const char *s;
char *p;
unsigned char *q;
BUF_MEM *b = NULL;
static const char hex[17] = "0123456789ABCDEF";
int gs_doit[4];
char tmp_buf[80];
#ifdef CHARSET_EBCDIC
unsigned char ebcdic_buf[1024];
#endif
if (buf == NULL) {
if ((b = BUF_MEM_new()) == NULL)
goto err;
if (!BUF_MEM_grow(b, 200))
goto err;
b->data[0] = '\0';
len = 200;
} else if (len == 0) {
return NULL;
}
if (a == NULL) {
if (b) {
buf = b->data;
OPENSSL_free(b);
}
strncpy(buf, "NO X509_NAME", len);
buf[len - 1] = '\0';
return buf;
}
len--; /* space for '\0' */
l = 0;
for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
ne = sk_X509_NAME_ENTRY_value(a->entries, i);
n = OBJ_obj2nid(ne->object);
if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
i2t_ASN1_OBJECT(tmp_buf, sizeof(tmp_buf), ne->object);
s = tmp_buf;
}
l1 = strlen(s);
type = ne->value->type;
num = ne->value->length;
if (num > NAME_ONELINE_MAX) {
X509err(X509_F_X509_NAME_ONELINE, X509_R_NAME_TOO_LONG);
goto end;
}
q = ne->value->data;
#ifdef CHARSET_EBCDIC
if (type == V_ASN1_GENERALSTRING ||
type == V_ASN1_VISIBLESTRING ||
type == V_ASN1_PRINTABLESTRING ||
type == V_ASN1_TELETEXSTRING ||
type == V_ASN1_IA5STRING) {
if (num > (int)sizeof(ebcdic_buf))
num = sizeof(ebcdic_buf);
ascii2ebcdic(ebcdic_buf, q, num);
q = ebcdic_buf;
}
#endif
if ((type == V_ASN1_GENERALSTRING) && ((num % 4) == 0)) {
gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 0;
for (j = 0; j < num; j++)
if (q[j] != 0)
gs_doit[j & 3] = 1;
if (gs_doit[0] | gs_doit[1] | gs_doit[2])
gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 1;
else {
gs_doit[0] = gs_doit[1] = gs_doit[2] = 0;
gs_doit[3] = 1;
}
} else
gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 1;
for (l2 = j = 0; j < num; j++) {
if (!gs_doit[j & 3])
continue;
l2++;
#ifndef CHARSET_EBCDIC
if ((q[j] < ' ') || (q[j] > '~'))
l2 += 3;
#else
if ((os_toascii[q[j]] < os_toascii[' ']) ||
(os_toascii[q[j]] > os_toascii['~']))
l2 += 3;
#endif
}
lold = l;
l += 1 + l1 + 1 + l2;
if (l > NAME_ONELINE_MAX) {
X509err(X509_F_X509_NAME_ONELINE, X509_R_NAME_TOO_LONG);
goto end;
}
if (b != NULL) {
if (!BUF_MEM_grow(b, l + 1))
goto err;
p = &(b->data[lold]);
} else if (l > len) {
break;
} else
p = &(buf[lold]);
*(p++) = '/';
memcpy(p, s, (unsigned int)l1);
p += l1;
*(p++) = '=';
#ifndef CHARSET_EBCDIC /* q was assigned above already. */
q = ne->value->data;
#endif
for (j = 0; j < num; j++) {
if (!gs_doit[j & 3])
continue;
#ifndef CHARSET_EBCDIC
n = q[j];
if ((n < ' ') || (n > '~')) {
*(p++) = '\\';
*(p++) = 'x';
*(p++) = hex[(n >> 4) & 0x0f];
*(p++) = hex[n & 0x0f];
} else
*(p++) = n;
#else
n = os_toascii[q[j]];
if ((n < os_toascii[' ']) || (n > os_toascii['~'])) {
*(p++) = '\\';
*(p++) = 'x';
*(p++) = hex[(n >> 4) & 0x0f];
*(p++) = hex[n & 0x0f];
} else
*(p++) = q[j];
#endif
}
*p = '\0';
}
if (b != NULL) {
p = b->data;
OPENSSL_free(b);
} else
p = buf;
if (i == 0)
*p = '\0';
return p;
err:
X509err(X509_F_X509_NAME_ONELINE, ERR_R_MALLOC_FAILURE);
end:
BUF_MEM_free(b);
return NULL;
}

View file

@ -0,0 +1,67 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/asn1.h>
#include <openssl/x509.h>
#include "internal/x509_int.h"
#include <openssl/objects.h>
#include <openssl/buffer.h>
X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey)
{
X509 *ret = NULL;
X509_CINF *xi = NULL;
X509_NAME *xn;
EVP_PKEY *pubkey = NULL;
if ((ret = X509_new()) == NULL) {
X509err(X509_F_X509_REQ_TO_X509, ERR_R_MALLOC_FAILURE);
return NULL;
}
/* duplicate the request */
xi = &ret->cert_info;
if (sk_X509_ATTRIBUTE_num(r->req_info.attributes) != 0) {
if ((xi->version = ASN1_INTEGER_new()) == NULL)
goto err;
if (!ASN1_INTEGER_set(xi->version, 2))
goto err;
/*- xi->extensions=ri->attributes; <- bad, should not ever be done
ri->attributes=NULL; */
}
xn = X509_REQ_get_subject_name(r);
if (X509_set_subject_name(ret, xn) == 0)
goto err;
if (X509_set_issuer_name(ret, xn) == 0)
goto err;
if (X509_gmtime_adj(xi->validity.notBefore, 0) == NULL)
goto err;
if (X509_gmtime_adj(xi->validity.notAfter, (long)60 * 60 * 24 * days) ==
NULL)
goto err;
pubkey = X509_REQ_get0_pubkey(r);
if (pubkey == NULL || !X509_set_pubkey(ret, pubkey))
goto err;
if (!X509_sign(ret, pkey, EVP_md5()))
goto err;
return ret;
err:
X509_free(ret);
return NULL;
}

View file

@ -0,0 +1,298 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include "internal/x509_int.h"
#include <openssl/objects.h>
#include <openssl/buffer.h>
#include <openssl/pem.h>
X509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
{
X509_REQ *ret;
X509_REQ_INFO *ri;
int i;
EVP_PKEY *pktmp;
ret = X509_REQ_new();
if (ret == NULL) {
X509err(X509_F_X509_TO_X509_REQ, ERR_R_MALLOC_FAILURE);
goto err;
}
ri = &ret->req_info;
ri->version->length = 1;
ri->version->data = OPENSSL_malloc(1);
if (ri->version->data == NULL)
goto err;
ri->version->data[0] = 0; /* version == 0 */
if (!X509_REQ_set_subject_name(ret, X509_get_subject_name(x)))
goto err;
pktmp = X509_get0_pubkey(x);
if (pktmp == NULL)
goto err;
i = X509_REQ_set_pubkey(ret, pktmp);
if (!i)
goto err;
if (pkey != NULL) {
if (!X509_REQ_sign(ret, pkey, md))
goto err;
}
return ret;
err:
X509_REQ_free(ret);
return NULL;
}
EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req)
{
if (req == NULL)
return NULL;
return X509_PUBKEY_get(req->req_info.pubkey);
}
EVP_PKEY *X509_REQ_get0_pubkey(X509_REQ *req)
{
if (req == NULL)
return NULL;
return X509_PUBKEY_get0(req->req_info.pubkey);
}
X509_PUBKEY *X509_REQ_get_X509_PUBKEY(X509_REQ *req)
{
return req->req_info.pubkey;
}
int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k)
{
EVP_PKEY *xk = NULL;
int ok = 0;
xk = X509_REQ_get_pubkey(x);
switch (EVP_PKEY_cmp(xk, k)) {
case 1:
ok = 1;
break;
case 0:
X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY,
X509_R_KEY_VALUES_MISMATCH);
break;
case -1:
X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, X509_R_KEY_TYPE_MISMATCH);
break;
case -2:
#ifndef OPENSSL_NO_EC
if (EVP_PKEY_id(k) == EVP_PKEY_EC) {
X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, ERR_R_EC_LIB);
break;
}
#endif
#ifndef OPENSSL_NO_DH
if (EVP_PKEY_id(k) == EVP_PKEY_DH) {
/* No idea */
X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY,
X509_R_CANT_CHECK_DH_KEY);
break;
}
#endif
X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, X509_R_UNKNOWN_KEY_TYPE);
}
EVP_PKEY_free(xk);
return ok;
}
/*
* It seems several organisations had the same idea of including a list of
* extensions in a certificate request. There are at least two OIDs that are
* used and there may be more: so the list is configurable.
*/
static int ext_nid_list[] = { NID_ext_req, NID_ms_ext_req, NID_undef };
static int *ext_nids = ext_nid_list;
int X509_REQ_extension_nid(int req_nid)
{
int i, nid;
for (i = 0;; i++) {
nid = ext_nids[i];
if (nid == NID_undef)
return 0;
else if (req_nid == nid)
return 1;
}
}
int *X509_REQ_get_extension_nids(void)
{
return ext_nids;
}
void X509_REQ_set_extension_nids(int *nids)
{
ext_nids = nids;
}
STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req)
{
X509_ATTRIBUTE *attr;
ASN1_TYPE *ext = NULL;
int idx, *pnid;
const unsigned char *p;
if ((req == NULL) || !ext_nids)
return NULL;
for (pnid = ext_nids; *pnid != NID_undef; pnid++) {
idx = X509_REQ_get_attr_by_NID(req, *pnid, -1);
if (idx == -1)
continue;
attr = X509_REQ_get_attr(req, idx);
ext = X509_ATTRIBUTE_get0_type(attr, 0);
break;
}
if (!ext || (ext->type != V_ASN1_SEQUENCE))
return NULL;
p = ext->value.sequence->data;
return (STACK_OF(X509_EXTENSION) *)
ASN1_item_d2i(NULL, &p, ext->value.sequence->length,
ASN1_ITEM_rptr(X509_EXTENSIONS));
}
/*
* Add a STACK_OF extensions to a certificate request: allow alternative OIDs
* in case we want to create a non standard one.
*/
int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts,
int nid)
{
int extlen;
int rv = 0;
unsigned char *ext = NULL;
/* Generate encoding of extensions */
extlen = ASN1_item_i2d((ASN1_VALUE *)exts, &ext,
ASN1_ITEM_rptr(X509_EXTENSIONS));
if (extlen <= 0)
return 0;
rv = X509_REQ_add1_attr_by_NID(req, nid, V_ASN1_SEQUENCE, ext, extlen);
OPENSSL_free(ext);
return rv;
}
/* This is the normal usage: use the "official" OID */
int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts)
{
return X509_REQ_add_extensions_nid(req, exts, NID_ext_req);
}
/* Request attribute functions */
int X509_REQ_get_attr_count(const X509_REQ *req)
{
return X509at_get_attr_count(req->req_info.attributes);
}
int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos)
{
return X509at_get_attr_by_NID(req->req_info.attributes, nid, lastpos);
}
int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, const ASN1_OBJECT *obj,
int lastpos)
{
return X509at_get_attr_by_OBJ(req->req_info.attributes, obj, lastpos);
}
X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc)
{
return X509at_get_attr(req->req_info.attributes, loc);
}
X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc)
{
return X509at_delete_attr(req->req_info.attributes, loc);
}
int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr)
{
if (X509at_add1_attr(&req->req_info.attributes, attr))
return 1;
return 0;
}
int X509_REQ_add1_attr_by_OBJ(X509_REQ *req,
const ASN1_OBJECT *obj, int type,
const unsigned char *bytes, int len)
{
if (X509at_add1_attr_by_OBJ(&req->req_info.attributes, obj,
type, bytes, len))
return 1;
return 0;
}
int X509_REQ_add1_attr_by_NID(X509_REQ *req,
int nid, int type,
const unsigned char *bytes, int len)
{
if (X509at_add1_attr_by_NID(&req->req_info.attributes, nid,
type, bytes, len))
return 1;
return 0;
}
int X509_REQ_add1_attr_by_txt(X509_REQ *req,
const char *attrname, int type,
const unsigned char *bytes, int len)
{
if (X509at_add1_attr_by_txt(&req->req_info.attributes, attrname,
type, bytes, len))
return 1;
return 0;
}
long X509_REQ_get_version(const X509_REQ *req)
{
return ASN1_INTEGER_get(req->req_info.version);
}
X509_NAME *X509_REQ_get_subject_name(const X509_REQ *req)
{
return req->req_info.subject;
}
void X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig,
const X509_ALGOR **palg)
{
if (psig != NULL)
*psig = req->signature;
if (palg != NULL)
*palg = &req->sig_alg;
}
int X509_REQ_get_signature_nid(const X509_REQ *req)
{
return OBJ_obj2nid(req->sig_alg.algorithm);
}
int i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp)
{
req->req_info.enc.modified = 1;
return i2d_X509_REQ_INFO(&req->req_info, pp);
}

View file

@ -0,0 +1,237 @@
/*
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include "internal/refcount.h"
#include <openssl/asn1.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "internal/asn1_int.h"
#include "internal/x509_int.h"
#include "x509_lcl.h"
int X509_set_version(X509 *x, long version)
{
if (x == NULL)
return 0;
if (version == 0) {
ASN1_INTEGER_free(x->cert_info.version);
x->cert_info.version = NULL;
return 1;
}
if (x->cert_info.version == NULL) {
if ((x->cert_info.version = ASN1_INTEGER_new()) == NULL)
return 0;
}
return ASN1_INTEGER_set(x->cert_info.version, version);
}
int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial)
{
ASN1_INTEGER *in;
if (x == NULL)
return 0;
in = &x->cert_info.serialNumber;
if (in != serial)
return ASN1_STRING_copy(in, serial);
return 1;
}
int X509_set_issuer_name(X509 *x, X509_NAME *name)
{
if (x == NULL)
return 0;
return X509_NAME_set(&x->cert_info.issuer, name);
}
int X509_set_subject_name(X509 *x, X509_NAME *name)
{
if (x == NULL)
return 0;
return X509_NAME_set(&x->cert_info.subject, name);
}
int x509_set1_time(ASN1_TIME **ptm, const ASN1_TIME *tm)
{
ASN1_TIME *in;
in = *ptm;
if (in != tm) {
in = ASN1_STRING_dup(tm);
if (in != NULL) {
ASN1_TIME_free(*ptm);
*ptm = in;
}
}
return (in != NULL);
}
int X509_set1_notBefore(X509 *x, const ASN1_TIME *tm)
{
if (x == NULL)
return 0;
return x509_set1_time(&x->cert_info.validity.notBefore, tm);
}
int X509_set1_notAfter(X509 *x, const ASN1_TIME *tm)
{
if (x == NULL)
return 0;
return x509_set1_time(&x->cert_info.validity.notAfter, tm);
}
int X509_set_pubkey(X509 *x, EVP_PKEY *pkey)
{
if (x == NULL)
return 0;
return X509_PUBKEY_set(&(x->cert_info.key), pkey);
}
int X509_up_ref(X509 *x)
{
int i;
if (CRYPTO_UP_REF(&x->references, &i, x->lock) <= 0)
return 0;
REF_PRINT_COUNT("X509", x);
REF_ASSERT_ISNT(i < 2);
return ((i > 1) ? 1 : 0);
}
long X509_get_version(const X509 *x)
{
return ASN1_INTEGER_get(x->cert_info.version);
}
const ASN1_TIME *X509_get0_notBefore(const X509 *x)
{
return x->cert_info.validity.notBefore;
}
const ASN1_TIME *X509_get0_notAfter(const X509 *x)
{
return x->cert_info.validity.notAfter;
}
ASN1_TIME *X509_getm_notBefore(const X509 *x)
{
return x->cert_info.validity.notBefore;
}
ASN1_TIME *X509_getm_notAfter(const X509 *x)
{
return x->cert_info.validity.notAfter;
}
int X509_get_signature_type(const X509 *x)
{
return EVP_PKEY_type(OBJ_obj2nid(x->sig_alg.algorithm));
}
X509_PUBKEY *X509_get_X509_PUBKEY(const X509 *x)
{
return x->cert_info.key;
}
const STACK_OF(X509_EXTENSION) *X509_get0_extensions(const X509 *x)
{
return x->cert_info.extensions;
}
void X509_get0_uids(const X509 *x, const ASN1_BIT_STRING **piuid,
const ASN1_BIT_STRING **psuid)
{
if (piuid != NULL)
*piuid = x->cert_info.issuerUID;
if (psuid != NULL)
*psuid = x->cert_info.subjectUID;
}
const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x)
{
return &x->cert_info.signature;
}
int X509_SIG_INFO_get(const X509_SIG_INFO *siginf, int *mdnid, int *pknid,
int *secbits, uint32_t *flags)
{
if (mdnid != NULL)
*mdnid = siginf->mdnid;
if (pknid != NULL)
*pknid = siginf->pknid;
if (secbits != NULL)
*secbits = siginf->secbits;
if (flags != NULL)
*flags = siginf->flags;
return (siginf->flags & X509_SIG_INFO_VALID) != 0;
}
void X509_SIG_INFO_set(X509_SIG_INFO *siginf, int mdnid, int pknid,
int secbits, uint32_t flags)
{
siginf->mdnid = mdnid;
siginf->pknid = pknid;
siginf->secbits = secbits;
siginf->flags = flags;
}
int X509_get_signature_info(X509 *x, int *mdnid, int *pknid, int *secbits,
uint32_t *flags)
{
X509_check_purpose(x, -1, -1);
return X509_SIG_INFO_get(&x->siginf, mdnid, pknid, secbits, flags);
}
static void x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
const ASN1_STRING *sig)
{
int pknid, mdnid;
const EVP_MD *md;
siginf->mdnid = NID_undef;
siginf->pknid = NID_undef;
siginf->secbits = -1;
siginf->flags = 0;
if (!OBJ_find_sigid_algs(OBJ_obj2nid(alg->algorithm), &mdnid, &pknid)
|| pknid == NID_undef)
return;
siginf->pknid = pknid;
if (mdnid == NID_undef) {
/* If we have one, use a custom handler for this algorithm */
const EVP_PKEY_ASN1_METHOD *ameth = EVP_PKEY_asn1_find(NULL, pknid);
if (ameth == NULL || ameth->siginf_set == NULL
|| ameth->siginf_set(siginf, alg, sig) == 0)
return;
siginf->flags |= X509_SIG_INFO_VALID;
return;
}
siginf->flags |= X509_SIG_INFO_VALID;
siginf->mdnid = mdnid;
md = EVP_get_digestbynid(mdnid);
if (md == NULL)
return;
/* Security bits: half number of bits in digest */
siginf->secbits = EVP_MD_size(md) * 4;
switch (mdnid) {
case NID_sha1:
case NID_sha256:
case NID_sha384:
case NID_sha512:
siginf->flags |= X509_SIG_INFO_TLS;
}
}
void x509_init_sig_info(X509 *x)
{
x509_sig_info_init(&x->siginf, &x->sig_alg, &x->signature);
}

View file

@ -0,0 +1,299 @@
/*
* Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/x509v3.h>
#include "internal/x509_int.h"
static int tr_cmp(const X509_TRUST *const *a, const X509_TRUST *const *b);
static void trtable_free(X509_TRUST *p);
static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags);
static int trust_1oid(X509_TRUST *trust, X509 *x, int flags);
static int trust_compat(X509_TRUST *trust, X509 *x, int flags);
static int obj_trust(int id, X509 *x, int flags);
static int (*default_trust) (int id, X509 *x, int flags) = obj_trust;
/*
* WARNING: the following table should be kept in order of trust and without
* any gaps so we can just subtract the minimum trust value to get an index
* into the table
*/
static X509_TRUST trstandard[] = {
{X509_TRUST_COMPAT, 0, trust_compat, "compatible", 0, NULL},
{X509_TRUST_SSL_CLIENT, 0, trust_1oidany, "SSL Client", NID_client_auth,
NULL},
{X509_TRUST_SSL_SERVER, 0, trust_1oidany, "SSL Server", NID_server_auth,
NULL},
{X509_TRUST_EMAIL, 0, trust_1oidany, "S/MIME email", NID_email_protect,
NULL},
{X509_TRUST_OBJECT_SIGN, 0, trust_1oidany, "Object Signer", NID_code_sign,
NULL},
{X509_TRUST_OCSP_SIGN, 0, trust_1oid, "OCSP responder", NID_OCSP_sign,
NULL},
{X509_TRUST_OCSP_REQUEST, 0, trust_1oid, "OCSP request", NID_ad_OCSP,
NULL},
{X509_TRUST_TSA, 0, trust_1oidany, "TSA server", NID_time_stamp, NULL}
};
#define X509_TRUST_COUNT OSSL_NELEM(trstandard)
static STACK_OF(X509_TRUST) *trtable = NULL;
static int tr_cmp(const X509_TRUST *const *a, const X509_TRUST *const *b)
{
return (*a)->trust - (*b)->trust;
}
int (*X509_TRUST_set_default(int (*trust) (int, X509 *, int))) (int, X509 *,
int) {
int (*oldtrust) (int, X509 *, int);
oldtrust = default_trust;
default_trust = trust;
return oldtrust;
}
int X509_check_trust(X509 *x, int id, int flags)
{
X509_TRUST *pt;
int idx;
/* We get this as a default value */
if (id == X509_TRUST_DEFAULT)
return obj_trust(NID_anyExtendedKeyUsage, x,
flags | X509_TRUST_DO_SS_COMPAT);
idx = X509_TRUST_get_by_id(id);
if (idx == -1)
return default_trust(id, x, flags);
pt = X509_TRUST_get0(idx);
return pt->check_trust(pt, x, flags);
}
int X509_TRUST_get_count(void)
{
if (!trtable)
return X509_TRUST_COUNT;
return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT;
}
X509_TRUST *X509_TRUST_get0(int idx)
{
if (idx < 0)
return NULL;
if (idx < (int)X509_TRUST_COUNT)
return trstandard + idx;
return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT);
}
int X509_TRUST_get_by_id(int id)
{
X509_TRUST tmp;
int idx;
if ((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX))
return id - X509_TRUST_MIN;
if (trtable == NULL)
return -1;
tmp.trust = id;
idx = sk_X509_TRUST_find(trtable, &tmp);
if (idx < 0)
return -1;
return idx + X509_TRUST_COUNT;
}
int X509_TRUST_set(int *t, int trust)
{
if (X509_TRUST_get_by_id(trust) == -1) {
X509err(X509_F_X509_TRUST_SET, X509_R_INVALID_TRUST);
return 0;
}
*t = trust;
return 1;
}
int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int),
const char *name, int arg1, void *arg2)
{
int idx;
X509_TRUST *trtmp;
/*
* This is set according to what we change: application can't set it
*/
flags &= ~X509_TRUST_DYNAMIC;
/* This will always be set for application modified trust entries */
flags |= X509_TRUST_DYNAMIC_NAME;
/* Get existing entry if any */
idx = X509_TRUST_get_by_id(id);
/* Need a new entry */
if (idx == -1) {
if ((trtmp = OPENSSL_malloc(sizeof(*trtmp))) == NULL) {
X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
return 0;
}
trtmp->flags = X509_TRUST_DYNAMIC;
} else
trtmp = X509_TRUST_get0(idx);
/* OPENSSL_free existing name if dynamic */
if (trtmp->flags & X509_TRUST_DYNAMIC_NAME)
OPENSSL_free(trtmp->name);
/* dup supplied name */
if ((trtmp->name = OPENSSL_strdup(name)) == NULL) {
X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
goto err;
}
/* Keep the dynamic flag of existing entry */
trtmp->flags &= X509_TRUST_DYNAMIC;
/* Set all other flags */
trtmp->flags |= flags;
trtmp->trust = id;
trtmp->check_trust = ck;
trtmp->arg1 = arg1;
trtmp->arg2 = arg2;
/* If its a new entry manage the dynamic table */
if (idx == -1) {
if (trtable == NULL
&& (trtable = sk_X509_TRUST_new(tr_cmp)) == NULL) {
X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
goto err;;
}
if (!sk_X509_TRUST_push(trtable, trtmp)) {
X509err(X509_F_X509_TRUST_ADD, ERR_R_MALLOC_FAILURE);
goto err;
}
}
return 1;
err:
if (idx == -1) {
OPENSSL_free(trtmp->name);
OPENSSL_free(trtmp);
}
return 0;
}
static void trtable_free(X509_TRUST *p)
{
if (!p)
return;
if (p->flags & X509_TRUST_DYNAMIC) {
if (p->flags & X509_TRUST_DYNAMIC_NAME)
OPENSSL_free(p->name);
OPENSSL_free(p);
}
}
void X509_TRUST_cleanup(void)
{
sk_X509_TRUST_pop_free(trtable, trtable_free);
trtable = NULL;
}
int X509_TRUST_get_flags(const X509_TRUST *xp)
{
return xp->flags;
}
char *X509_TRUST_get0_name(const X509_TRUST *xp)
{
return xp->name;
}
int X509_TRUST_get_trust(const X509_TRUST *xp)
{
return xp->trust;
}
static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags)
{
/*
* Declare the chain verified if the desired trust OID is not rejected in
* any auxiliary trust info for this certificate, and the OID is either
* expressly trusted, or else either "anyEKU" is trusted, or the
* certificate is self-signed.
*/
flags |= X509_TRUST_DO_SS_COMPAT | X509_TRUST_OK_ANY_EKU;
return obj_trust(trust->arg1, x, flags);
}
static int trust_1oid(X509_TRUST *trust, X509 *x, int flags)
{
/*
* Declare the chain verified only if the desired trust OID is not
* rejected and is expressly trusted. Neither "anyEKU" nor "compat"
* trust in self-signed certificates apply.
*/
flags &= ~(X509_TRUST_DO_SS_COMPAT | X509_TRUST_OK_ANY_EKU);
return obj_trust(trust->arg1, x, flags);
}
static int trust_compat(X509_TRUST *trust, X509 *x, int flags)
{
/* Call for side-effect of computing hash and caching extensions */
X509_check_purpose(x, -1, 0);
if ((flags & X509_TRUST_NO_SS_COMPAT) == 0 && x->ex_flags & EXFLAG_SS)
return X509_TRUST_TRUSTED;
else
return X509_TRUST_UNTRUSTED;
}
static int obj_trust(int id, X509 *x, int flags)
{
X509_CERT_AUX *ax = x->aux;
int i;
if (ax && ax->reject) {
for (i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) {
ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(ax->reject, i);
int nid = OBJ_obj2nid(obj);
if (nid == id || (nid == NID_anyExtendedKeyUsage &&
(flags & X509_TRUST_OK_ANY_EKU)))
return X509_TRUST_REJECTED;
}
}
if (ax && ax->trust) {
for (i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) {
ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(ax->trust, i);
int nid = OBJ_obj2nid(obj);
if (nid == id || (nid == NID_anyExtendedKeyUsage &&
(flags & X509_TRUST_OK_ANY_EKU)))
return X509_TRUST_TRUSTED;
}
/*
* Reject when explicit trust EKU are set and none match.
*
* Returning untrusted is enough for for full chains that end in
* self-signed roots, because when explicit trust is specified it
* suppresses the default blanket trust of self-signed objects.
*
* But for partial chains, this is not enough, because absent a similar
* trust-self-signed policy, non matching EKUs are indistinguishable
* from lack of EKU constraints.
*
* Therefore, failure to match any trusted purpose must trigger an
* explicit reject.
*/
return X509_TRUST_REJECTED;
}
if ((flags & X509_TRUST_DO_SS_COMPAT) == 0)
return X509_TRUST_UNTRUSTED;
/*
* Not rejected, and there is no list of accepted uses, try compat.
*/
return trust_compat(NULL, x, flags);
}

View file

@ -0,0 +1,182 @@
/*
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include "internal/cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/evp.h>
#include <openssl/asn1.h>
#include <openssl/x509.h>
#include <openssl/objects.h>
const char *X509_verify_cert_error_string(long n)
{
switch ((int)n) {
case X509_V_OK:
return "ok";
case X509_V_ERR_UNSPECIFIED:
return "unspecified certificate verification error";
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
return "unable to get issuer certificate";
case X509_V_ERR_UNABLE_TO_GET_CRL:
return "unable to get certificate CRL";
case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
return "unable to decrypt certificate's signature";
case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
return "unable to decrypt CRL's signature";
case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
return "unable to decode issuer public key";
case X509_V_ERR_CERT_SIGNATURE_FAILURE:
return "certificate signature failure";
case X509_V_ERR_CRL_SIGNATURE_FAILURE:
return "CRL signature failure";
case X509_V_ERR_CERT_NOT_YET_VALID:
return "certificate is not yet valid";
case X509_V_ERR_CERT_HAS_EXPIRED:
return "certificate has expired";
case X509_V_ERR_CRL_NOT_YET_VALID:
return "CRL is not yet valid";
case X509_V_ERR_CRL_HAS_EXPIRED:
return "CRL has expired";
case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
return "format error in certificate's notBefore field";
case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
return "format error in certificate's notAfter field";
case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
return "format error in CRL's lastUpdate field";
case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
return "format error in CRL's nextUpdate field";
case X509_V_ERR_OUT_OF_MEM:
return "out of memory";
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
return "self signed certificate";
case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
return "self signed certificate in certificate chain";
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
return "unable to get local issuer certificate";
case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
return "unable to verify the first certificate";
case X509_V_ERR_CERT_CHAIN_TOO_LONG:
return "certificate chain too long";
case X509_V_ERR_CERT_REVOKED:
return "certificate revoked";
case X509_V_ERR_INVALID_CA:
return "invalid CA certificate";
case X509_V_ERR_PATH_LENGTH_EXCEEDED:
return "path length constraint exceeded";
case X509_V_ERR_INVALID_PURPOSE:
return "unsupported certificate purpose";
case X509_V_ERR_CERT_UNTRUSTED:
return "certificate not trusted";
case X509_V_ERR_CERT_REJECTED:
return "certificate rejected";
case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
return "subject issuer mismatch";
case X509_V_ERR_AKID_SKID_MISMATCH:
return "authority and subject key identifier mismatch";
case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH:
return "authority and issuer serial number mismatch";
case X509_V_ERR_KEYUSAGE_NO_CERTSIGN:
return "key usage does not include certificate signing";
case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
return "unable to get CRL issuer certificate";
case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
return "unhandled critical extension";
case X509_V_ERR_KEYUSAGE_NO_CRL_SIGN:
return "key usage does not include CRL signing";
case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION:
return "unhandled critical CRL extension";
case X509_V_ERR_INVALID_NON_CA:
return "invalid non-CA certificate (has CA markings)";
case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED:
return "proxy path length constraint exceeded";
case X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE:
return "key usage does not include digital signature";
case X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED:
return
"proxy certificates not allowed, please set the appropriate flag";
case X509_V_ERR_INVALID_EXTENSION:
return "invalid or inconsistent certificate extension";
case X509_V_ERR_INVALID_POLICY_EXTENSION:
return "invalid or inconsistent certificate policy extension";
case X509_V_ERR_NO_EXPLICIT_POLICY:
return "no explicit policy";
case X509_V_ERR_DIFFERENT_CRL_SCOPE:
return "Different CRL scope";
case X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE:
return "Unsupported extension feature";
case X509_V_ERR_UNNESTED_RESOURCE:
return "RFC 3779 resource not subset of parent's resources";
case X509_V_ERR_PERMITTED_VIOLATION:
return "permitted subtree violation";
case X509_V_ERR_EXCLUDED_VIOLATION:
return "excluded subtree violation";
case X509_V_ERR_SUBTREE_MINMAX:
return "name constraints minimum and maximum not supported";
case X509_V_ERR_APPLICATION_VERIFICATION:
return "application verification failure";
case X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE:
return "unsupported name constraint type";
case X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX:
return "unsupported or invalid name constraint syntax";
case X509_V_ERR_UNSUPPORTED_NAME_SYNTAX:
return "unsupported or invalid name syntax";
case X509_V_ERR_CRL_PATH_VALIDATION_ERROR:
return "CRL path validation error";
case X509_V_ERR_PATH_LOOP:
return "Path Loop";
case X509_V_ERR_SUITE_B_INVALID_VERSION:
return "Suite B: certificate version invalid";
case X509_V_ERR_SUITE_B_INVALID_ALGORITHM:
return "Suite B: invalid public key algorithm";
case X509_V_ERR_SUITE_B_INVALID_CURVE:
return "Suite B: invalid ECC curve";
case X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM:
return "Suite B: invalid signature algorithm";
case X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED:
return "Suite B: curve not allowed for this LOS";
case X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256:
return "Suite B: cannot sign P-384 with P-256";
case X509_V_ERR_HOSTNAME_MISMATCH:
return "Hostname mismatch";
case X509_V_ERR_EMAIL_MISMATCH:
return "Email address mismatch";
case X509_V_ERR_IP_ADDRESS_MISMATCH:
return "IP address mismatch";
case X509_V_ERR_DANE_NO_MATCH:
return "No matching DANE TLSA records";
case X509_V_ERR_EE_KEY_TOO_SMALL:
return "EE certificate key too weak";
case X509_V_ERR_CA_KEY_TOO_SMALL:
return "CA certificate key too weak";
case X509_V_ERR_CA_MD_TOO_WEAK:
return "CA signature digest algorithm too weak";
case X509_V_ERR_INVALID_CALL:
return "Invalid certificate verification context";
case X509_V_ERR_STORE_LOOKUP:
return "Issuer certificate lookup error";
case X509_V_ERR_NO_VALID_SCTS:
return "Certificate Transparency required, but no valid SCTs found";
case X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION:
return "proxy subject name violation";
case X509_V_ERR_OCSP_VERIFY_NEEDED:
return "OCSP verification needed";
case X509_V_ERR_OCSP_VERIFY_FAILED:
return "OCSP verification failed";
case X509_V_ERR_OCSP_CERT_UNKNOWN:
return "OCSP unknown cert";
default:
/* Printing an error number into a static buffer is not thread-safe */
return "unknown certificate verification error";
}
}

View file

@ -0,0 +1,235 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/safestack.h>
#include <openssl/asn1.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "x509_lcl.h"
int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x)
{
if (x == NULL)
return 0;
return sk_X509_EXTENSION_num(x);
}
int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, int nid,
int lastpos)
{
ASN1_OBJECT *obj;
obj = OBJ_nid2obj(nid);
if (obj == NULL)
return -2;
return X509v3_get_ext_by_OBJ(x, obj, lastpos);
}
int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *sk,
const ASN1_OBJECT *obj, int lastpos)
{
int n;
X509_EXTENSION *ex;
if (sk == NULL)
return -1;
lastpos++;
if (lastpos < 0)
lastpos = 0;
n = sk_X509_EXTENSION_num(sk);
for (; lastpos < n; lastpos++) {
ex = sk_X509_EXTENSION_value(sk, lastpos);
if (OBJ_cmp(ex->object, obj) == 0)
return lastpos;
}
return -1;
}
int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *sk, int crit,
int lastpos)
{
int n;
X509_EXTENSION *ex;
if (sk == NULL)
return -1;
lastpos++;
if (lastpos < 0)
lastpos = 0;
n = sk_X509_EXTENSION_num(sk);
for (; lastpos < n; lastpos++) {
ex = sk_X509_EXTENSION_value(sk, lastpos);
if (((ex->critical > 0) && crit) || ((ex->critical <= 0) && !crit))
return lastpos;
}
return -1;
}
X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc)
{
if (x == NULL || sk_X509_EXTENSION_num(x) <= loc || loc < 0)
return NULL;
else
return sk_X509_EXTENSION_value(x, loc);
}
X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc)
{
X509_EXTENSION *ret;
if (x == NULL || sk_X509_EXTENSION_num(x) <= loc || loc < 0)
return NULL;
ret = sk_X509_EXTENSION_delete(x, loc);
return ret;
}
STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x,
X509_EXTENSION *ex, int loc)
{
X509_EXTENSION *new_ex = NULL;
int n;
STACK_OF(X509_EXTENSION) *sk = NULL;
if (x == NULL) {
X509err(X509_F_X509V3_ADD_EXT, ERR_R_PASSED_NULL_PARAMETER);
goto err2;
}
if (*x == NULL) {
if ((sk = sk_X509_EXTENSION_new_null()) == NULL)
goto err;
} else
sk = *x;
n = sk_X509_EXTENSION_num(sk);
if (loc > n)
loc = n;
else if (loc < 0)
loc = n;
if ((new_ex = X509_EXTENSION_dup(ex)) == NULL)
goto err2;
if (!sk_X509_EXTENSION_insert(sk, new_ex, loc))
goto err;
if (*x == NULL)
*x = sk;
return sk;
err:
X509err(X509_F_X509V3_ADD_EXT, ERR_R_MALLOC_FAILURE);
err2:
X509_EXTENSION_free(new_ex);
if (x != NULL && *x == NULL)
sk_X509_EXTENSION_free(sk);
return NULL;
}
X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid,
int crit,
ASN1_OCTET_STRING *data)
{
ASN1_OBJECT *obj;
X509_EXTENSION *ret;
obj = OBJ_nid2obj(nid);
if (obj == NULL) {
X509err(X509_F_X509_EXTENSION_CREATE_BY_NID, X509_R_UNKNOWN_NID);
return NULL;
}
ret = X509_EXTENSION_create_by_OBJ(ex, obj, crit, data);
if (ret == NULL)
ASN1_OBJECT_free(obj);
return ret;
}
X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex,
const ASN1_OBJECT *obj, int crit,
ASN1_OCTET_STRING *data)
{
X509_EXTENSION *ret;
if ((ex == NULL) || (*ex == NULL)) {
if ((ret = X509_EXTENSION_new()) == NULL) {
X509err(X509_F_X509_EXTENSION_CREATE_BY_OBJ,
ERR_R_MALLOC_FAILURE);
return NULL;
}
} else
ret = *ex;
if (!X509_EXTENSION_set_object(ret, obj))
goto err;
if (!X509_EXTENSION_set_critical(ret, crit))
goto err;
if (!X509_EXTENSION_set_data(ret, data))
goto err;
if ((ex != NULL) && (*ex == NULL))
*ex = ret;
return ret;
err:
if ((ex == NULL) || (ret != *ex))
X509_EXTENSION_free(ret);
return NULL;
}
int X509_EXTENSION_set_object(X509_EXTENSION *ex, const ASN1_OBJECT *obj)
{
if ((ex == NULL) || (obj == NULL))
return 0;
ASN1_OBJECT_free(ex->object);
ex->object = OBJ_dup(obj);
return ex->object != NULL;
}
int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit)
{
if (ex == NULL)
return 0;
ex->critical = (crit) ? 0xFF : -1;
return 1;
}
int X509_EXTENSION_set_data(X509_EXTENSION *ex, ASN1_OCTET_STRING *data)
{
int i;
if (ex == NULL)
return 0;
i = ASN1_OCTET_STRING_set(&ex->value, data->data, data->length);
if (!i)
return 0;
return 1;
}
ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *ex)
{
if (ex == NULL)
return NULL;
return ex->object;
}
ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ex)
{
if (ex == NULL)
return NULL;
return &ex->value;
}
int X509_EXTENSION_get_critical(const X509_EXTENSION *ex)
{
if (ex == NULL)
return 0;
if (ex->critical > 0)
return 1;
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,602 @@
/*
* Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/crypto.h>
#include <openssl/buffer.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "internal/x509_int.h"
#include "x509_lcl.h"
/* X509_VERIFY_PARAM functions */
#define SET_HOST 0
#define ADD_HOST 1
static char *str_copy(const char *s)
{
return OPENSSL_strdup(s);
}
static void str_free(char *s)
{
OPENSSL_free(s);
}
static int int_x509_param_set_hosts(X509_VERIFY_PARAM *vpm, int mode,
const char *name, size_t namelen)
{
char *copy;
/*
* Refuse names with embedded NUL bytes, except perhaps as final byte.
* XXX: Do we need to push an error onto the error stack?
*/
if (namelen == 0 || name == NULL)
namelen = name ? strlen(name) : 0;
else if (name && memchr(name, '\0', namelen > 1 ? namelen - 1 : namelen))
return 0;
if (namelen > 0 && name[namelen - 1] == '\0')
--namelen;
if (mode == SET_HOST) {
sk_OPENSSL_STRING_pop_free(vpm->hosts, str_free);
vpm->hosts = NULL;
}
if (name == NULL || namelen == 0)
return 1;
copy = OPENSSL_strndup(name, namelen);
if (copy == NULL)
return 0;
if (vpm->hosts == NULL &&
(vpm->hosts = sk_OPENSSL_STRING_new_null()) == NULL) {
OPENSSL_free(copy);
return 0;
}
if (!sk_OPENSSL_STRING_push(vpm->hosts, copy)) {
OPENSSL_free(copy);
if (sk_OPENSSL_STRING_num(vpm->hosts) == 0) {
sk_OPENSSL_STRING_free(vpm->hosts);
vpm->hosts = NULL;
}
return 0;
}
return 1;
}
X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void)
{
X509_VERIFY_PARAM *param;
param = OPENSSL_zalloc(sizeof(*param));
if (param == NULL) {
X509err(X509_F_X509_VERIFY_PARAM_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
param->trust = X509_TRUST_DEFAULT;
/* param->inh_flags = X509_VP_FLAG_DEFAULT; */
param->depth = -1;
param->auth_level = -1; /* -1 means unset, 0 is explicit */
return param;
}
void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param)
{
if (param == NULL)
return;
sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
sk_OPENSSL_STRING_pop_free(param->hosts, str_free);
OPENSSL_free(param->peername);
OPENSSL_free(param->email);
OPENSSL_free(param->ip);
OPENSSL_free(param);
}
/*-
* This function determines how parameters are "inherited" from one structure
* to another. There are several different ways this can happen.
*
* 1. If a child structure needs to have its values initialized from a parent
* they are simply copied across. For example SSL_CTX copied to SSL.
* 2. If the structure should take on values only if they are currently unset.
* For example the values in an SSL structure will take appropriate value
* for SSL servers or clients but only if the application has not set new
* ones.
*
* The "inh_flags" field determines how this function behaves.
*
* Normally any values which are set in the default are not copied from the
* destination and verify flags are ORed together.
*
* If X509_VP_FLAG_DEFAULT is set then anything set in the source is copied
* to the destination. Effectively the values in "to" become default values
* which will be used only if nothing new is set in "from".
*
* If X509_VP_FLAG_OVERWRITE is set then all value are copied across whether
* they are set or not. Flags is still Ored though.
*
* If X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead
* of ORed.
*
* If X509_VP_FLAG_LOCKED is set then no values are copied.
*
* If X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed
* after the next call.
*/
/* Macro to test if a field should be copied from src to dest */
#define test_x509_verify_param_copy(field, def) \
(to_overwrite || \
((src->field != def) && (to_default || (dest->field == def))))
/* Macro to test and copy a field if necessary */
#define x509_verify_param_copy(field, def) \
if (test_x509_verify_param_copy(field, def)) \
dest->field = src->field
int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
const X509_VERIFY_PARAM *src)
{
unsigned long inh_flags;
int to_default, to_overwrite;
if (!src)
return 1;
inh_flags = dest->inh_flags | src->inh_flags;
if (inh_flags & X509_VP_FLAG_ONCE)
dest->inh_flags = 0;
if (inh_flags & X509_VP_FLAG_LOCKED)
return 1;
if (inh_flags & X509_VP_FLAG_DEFAULT)
to_default = 1;
else
to_default = 0;
if (inh_flags & X509_VP_FLAG_OVERWRITE)
to_overwrite = 1;
else
to_overwrite = 0;
x509_verify_param_copy(purpose, 0);
x509_verify_param_copy(trust, X509_TRUST_DEFAULT);
x509_verify_param_copy(depth, -1);
x509_verify_param_copy(auth_level, -1);
/* If overwrite or check time not set, copy across */
if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) {
dest->check_time = src->check_time;
dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME;
/* Don't need to copy flag: that is done below */
}
if (inh_flags & X509_VP_FLAG_RESET_FLAGS)
dest->flags = 0;
dest->flags |= src->flags;
if (test_x509_verify_param_copy(policies, NULL)) {
if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies))
return 0;
}
/* Copy the host flags if and only if we're copying the host list */
if (test_x509_verify_param_copy(hosts, NULL)) {
sk_OPENSSL_STRING_pop_free(dest->hosts, str_free);
dest->hosts = NULL;
if (src->hosts) {
dest->hosts =
sk_OPENSSL_STRING_deep_copy(src->hosts, str_copy, str_free);
if (dest->hosts == NULL)
return 0;
dest->hostflags = src->hostflags;
}
}
if (test_x509_verify_param_copy(email, NULL)) {
if (!X509_VERIFY_PARAM_set1_email(dest, src->email, src->emaillen))
return 0;
}
if (test_x509_verify_param_copy(ip, NULL)) {
if (!X509_VERIFY_PARAM_set1_ip(dest, src->ip, src->iplen))
return 0;
}
return 1;
}
int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
const X509_VERIFY_PARAM *from)
{
unsigned long save_flags = to->inh_flags;
int ret;
to->inh_flags |= X509_VP_FLAG_DEFAULT;
ret = X509_VERIFY_PARAM_inherit(to, from);
to->inh_flags = save_flags;
return ret;
}
static int int_x509_param_set1(char **pdest, size_t *pdestlen,
const char *src, size_t srclen)
{
void *tmp;
if (src) {
if (srclen == 0)
srclen = strlen(src);
tmp = OPENSSL_memdup(src, srclen);
if (tmp == NULL)
return 0;
} else {
tmp = NULL;
srclen = 0;
}
OPENSSL_free(*pdest);
*pdest = tmp;
if (pdestlen != NULL)
*pdestlen = srclen;
return 1;
}
int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name)
{
OPENSSL_free(param->name);
param->name = OPENSSL_strdup(name);
if (param->name)
return 1;
return 0;
}
int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags)
{
param->flags |= flags;
if (flags & X509_V_FLAG_POLICY_MASK)
param->flags |= X509_V_FLAG_POLICY_CHECK;
return 1;
}
int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param,
unsigned long flags)
{
param->flags &= ~flags;
return 1;
}
unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param)
{
return param->flags;
}
uint32_t X509_VERIFY_PARAM_get_inh_flags(const X509_VERIFY_PARAM *param)
{
return param->inh_flags;
}
int X509_VERIFY_PARAM_set_inh_flags(X509_VERIFY_PARAM *param, uint32_t flags)
{
param->inh_flags = flags;
return 1;
}
int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose)
{
return X509_PURPOSE_set(&param->purpose, purpose);
}
int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust)
{
return X509_TRUST_set(&param->trust, trust);
}
void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth)
{
param->depth = depth;
}
void X509_VERIFY_PARAM_set_auth_level(X509_VERIFY_PARAM *param, int auth_level)
{
param->auth_level = auth_level;
}
time_t X509_VERIFY_PARAM_get_time(const X509_VERIFY_PARAM *param)
{
return param->check_time;
}
void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t)
{
param->check_time = t;
param->flags |= X509_V_FLAG_USE_CHECK_TIME;
}
int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param,
ASN1_OBJECT *policy)
{
if (!param->policies) {
param->policies = sk_ASN1_OBJECT_new_null();
if (!param->policies)
return 0;
}
if (!sk_ASN1_OBJECT_push(param->policies, policy))
return 0;
return 1;
}
int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
STACK_OF(ASN1_OBJECT) *policies)
{
int i;
ASN1_OBJECT *oid, *doid;
if (!param)
return 0;
sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
if (!policies) {
param->policies = NULL;
return 1;
}
param->policies = sk_ASN1_OBJECT_new_null();
if (!param->policies)
return 0;
for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++) {
oid = sk_ASN1_OBJECT_value(policies, i);
doid = OBJ_dup(oid);
if (!doid)
return 0;
if (!sk_ASN1_OBJECT_push(param->policies, doid)) {
ASN1_OBJECT_free(doid);
return 0;
}
}
param->flags |= X509_V_FLAG_POLICY_CHECK;
return 1;
}
int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
const char *name, size_t namelen)
{
return int_x509_param_set_hosts(param, SET_HOST, name, namelen);
}
int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
const char *name, size_t namelen)
{
return int_x509_param_set_hosts(param, ADD_HOST, name, namelen);
}
void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
unsigned int flags)
{
param->hostflags = flags;
}
unsigned int X509_VERIFY_PARAM_get_hostflags(const X509_VERIFY_PARAM *param)
{
return param->hostflags;
}
char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param)
{
return param->peername;
}
/*
* Move peername from one param structure to another, freeing any name present
* at the target. If the source is a NULL parameter structure, free and zero
* the target peername.
*/
void X509_VERIFY_PARAM_move_peername(X509_VERIFY_PARAM *to,
X509_VERIFY_PARAM *from)
{
char *peername = (from != NULL) ? from->peername : NULL;
if (to->peername != peername) {
OPENSSL_free(to->peername);
to->peername = peername;
}
if (from)
from->peername = NULL;
}
int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
const char *email, size_t emaillen)
{
return int_x509_param_set1(&param->email, &param->emaillen,
email, emaillen);
}
int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
const unsigned char *ip, size_t iplen)
{
if (iplen != 0 && iplen != 4 && iplen != 16)
return 0;
return int_x509_param_set1((char **)&param->ip, &param->iplen,
(char *)ip, iplen);
}
int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc)
{
unsigned char ipout[16];
size_t iplen;
iplen = (size_t)a2i_ipadd(ipout, ipasc);
if (iplen == 0)
return 0;
return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
}
int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param)
{
return param->depth;
}
int X509_VERIFY_PARAM_get_auth_level(const X509_VERIFY_PARAM *param)
{
return param->auth_level;
}
const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param)
{
return param->name;
}
#define vpm_empty_id NULL, 0U, NULL, NULL, 0, NULL, 0
/*
* Default verify parameters: these are used for various applications and can
* be overridden by the user specified table. NB: the 'name' field *must* be
* in alphabetical order because it will be searched using OBJ_search.
*/
static const X509_VERIFY_PARAM default_table[] = {
{
"default", /* X509 default parameters */
0, /* Check time */
0, /* internal flags */
X509_V_FLAG_TRUSTED_FIRST, /* flags */
0, /* purpose */
0, /* trust */
100, /* depth */
-1, /* auth_level */
NULL, /* policies */
vpm_empty_id},
{
"pkcs7", /* S/MIME sign parameters */
0, /* Check time */
0, /* internal flags */
0, /* flags */
X509_PURPOSE_SMIME_SIGN, /* purpose */
X509_TRUST_EMAIL, /* trust */
-1, /* depth */
-1, /* auth_level */
NULL, /* policies */
vpm_empty_id},
{
"smime_sign", /* S/MIME sign parameters */
0, /* Check time */
0, /* internal flags */
0, /* flags */
X509_PURPOSE_SMIME_SIGN, /* purpose */
X509_TRUST_EMAIL, /* trust */
-1, /* depth */
-1, /* auth_level */
NULL, /* policies */
vpm_empty_id},
{
"ssl_client", /* SSL/TLS client parameters */
0, /* Check time */
0, /* internal flags */
0, /* flags */
X509_PURPOSE_SSL_CLIENT, /* purpose */
X509_TRUST_SSL_CLIENT, /* trust */
-1, /* depth */
-1, /* auth_level */
NULL, /* policies */
vpm_empty_id},
{
"ssl_server", /* SSL/TLS server parameters */
0, /* Check time */
0, /* internal flags */
0, /* flags */
X509_PURPOSE_SSL_SERVER, /* purpose */
X509_TRUST_SSL_SERVER, /* trust */
-1, /* depth */
-1, /* auth_level */
NULL, /* policies */
vpm_empty_id}
};
static STACK_OF(X509_VERIFY_PARAM) *param_table = NULL;
static int table_cmp(const X509_VERIFY_PARAM *a, const X509_VERIFY_PARAM *b)
{
return strcmp(a->name, b->name);
}
DECLARE_OBJ_BSEARCH_CMP_FN(X509_VERIFY_PARAM, X509_VERIFY_PARAM, table);
IMPLEMENT_OBJ_BSEARCH_CMP_FN(X509_VERIFY_PARAM, X509_VERIFY_PARAM, table);
static int param_cmp(const X509_VERIFY_PARAM *const *a,
const X509_VERIFY_PARAM *const *b)
{
return strcmp((*a)->name, (*b)->name);
}
int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param)
{
int idx;
X509_VERIFY_PARAM *ptmp;
if (param_table == NULL) {
param_table = sk_X509_VERIFY_PARAM_new(param_cmp);
if (param_table == NULL)
return 0;
} else {
idx = sk_X509_VERIFY_PARAM_find(param_table, param);
if (idx >= 0) {
ptmp = sk_X509_VERIFY_PARAM_delete(param_table, idx);
X509_VERIFY_PARAM_free(ptmp);
}
}
if (!sk_X509_VERIFY_PARAM_push(param_table, param))
return 0;
return 1;
}
int X509_VERIFY_PARAM_get_count(void)
{
int num = OSSL_NELEM(default_table);
if (param_table)
num += sk_X509_VERIFY_PARAM_num(param_table);
return num;
}
const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id)
{
int num = OSSL_NELEM(default_table);
if (id < num)
return default_table + id;
return sk_X509_VERIFY_PARAM_value(param_table, id - num);
}
const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name)
{
int idx;
X509_VERIFY_PARAM pm;
pm.name = (char *)name;
if (param_table != NULL) {
idx = sk_X509_VERIFY_PARAM_find(param_table, &pm);
if (idx >= 0)
return sk_X509_VERIFY_PARAM_value(param_table, idx);
}
return OBJ_bsearch_table(&pm, default_table, OSSL_NELEM(default_table));
}
void X509_VERIFY_PARAM_table_cleanup(void)
{
sk_X509_VERIFY_PARAM_pop_free(param_table, X509_VERIFY_PARAM_free);
param_table = NULL;
}

View file

@ -0,0 +1,183 @@
/*
* Copyright 2001-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include "internal/refcount.h"
#include <openssl/asn1.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include "internal/x509_int.h"
int X509_CRL_set_version(X509_CRL *x, long version)
{
if (x == NULL)
return 0;
if (x->crl.version == NULL) {
if ((x->crl.version = ASN1_INTEGER_new()) == NULL)
return 0;
}
return ASN1_INTEGER_set(x->crl.version, version);
}
int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name)
{
if (x == NULL)
return 0;
return X509_NAME_set(&x->crl.issuer, name);
}
int X509_CRL_set1_lastUpdate(X509_CRL *x, const ASN1_TIME *tm)
{
if (x == NULL)
return 0;
return x509_set1_time(&x->crl.lastUpdate, tm);
}
int X509_CRL_set1_nextUpdate(X509_CRL *x, const ASN1_TIME *tm)
{
if (x == NULL)
return 0;
return x509_set1_time(&x->crl.nextUpdate, tm);
}
int X509_CRL_sort(X509_CRL *c)
{
int i;
X509_REVOKED *r;
/*
* sort the data so it will be written in serial number order
*/
sk_X509_REVOKED_sort(c->crl.revoked);
for (i = 0; i < sk_X509_REVOKED_num(c->crl.revoked); i++) {
r = sk_X509_REVOKED_value(c->crl.revoked, i);
r->sequence = i;
}
c->crl.enc.modified = 1;
return 1;
}
int X509_CRL_up_ref(X509_CRL *crl)
{
int i;
if (CRYPTO_UP_REF(&crl->references, &i, crl->lock) <= 0)
return 0;
REF_PRINT_COUNT("X509_CRL", crl);
REF_ASSERT_ISNT(i < 2);
return ((i > 1) ? 1 : 0);
}
long X509_CRL_get_version(const X509_CRL *crl)
{
return ASN1_INTEGER_get(crl->crl.version);
}
const ASN1_TIME *X509_CRL_get0_lastUpdate(const X509_CRL *crl)
{
return crl->crl.lastUpdate;
}
const ASN1_TIME *X509_CRL_get0_nextUpdate(const X509_CRL *crl)
{
return crl->crl.nextUpdate;
}
#if OPENSSL_API_COMPAT < 0x10100000L
ASN1_TIME *X509_CRL_get_lastUpdate(X509_CRL *crl)
{
return crl->crl.lastUpdate;
}
ASN1_TIME *X509_CRL_get_nextUpdate(X509_CRL *crl)
{
return crl->crl.nextUpdate;
}
#endif
X509_NAME *X509_CRL_get_issuer(const X509_CRL *crl)
{
return crl->crl.issuer;
}
const STACK_OF(X509_EXTENSION) *X509_CRL_get0_extensions(const X509_CRL *crl)
{
return crl->crl.extensions;
}
STACK_OF(X509_REVOKED) *X509_CRL_get_REVOKED(X509_CRL *crl)
{
return crl->crl.revoked;
}
void X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig,
const X509_ALGOR **palg)
{
if (psig != NULL)
*psig = &crl->signature;
if (palg != NULL)
*palg = &crl->sig_alg;
}
int X509_CRL_get_signature_nid(const X509_CRL *crl)
{
return OBJ_obj2nid(crl->sig_alg.algorithm);
}
const ASN1_TIME *X509_REVOKED_get0_revocationDate(const X509_REVOKED *x)
{
return x->revocationDate;
}
int X509_REVOKED_set_revocationDate(X509_REVOKED *x, ASN1_TIME *tm)
{
ASN1_TIME *in;
if (x == NULL)
return 0;
in = x->revocationDate;
if (in != tm) {
in = ASN1_STRING_dup(tm);
if (in != NULL) {
ASN1_TIME_free(x->revocationDate);
x->revocationDate = in;
}
}
return (in != NULL);
}
const ASN1_INTEGER *X509_REVOKED_get0_serialNumber(const X509_REVOKED *x)
{
return &x->serialNumber;
}
int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial)
{
ASN1_INTEGER *in;
if (x == NULL)
return 0;
in = &x->serialNumber;
if (in != serial)
return ASN1_STRING_copy(in, serial);
return 1;
}
const STACK_OF(X509_EXTENSION) *X509_REVOKED_get0_extensions(const X509_REVOKED *r)
{
return r->extensions;
}
int i2d_re_X509_CRL_tbs(X509_CRL *crl, unsigned char **pp)
{
crl->crl.enc.modified = 1;
return i2d_X509_CRL_INFO(&crl->crl, pp);
}

View file

@ -0,0 +1,360 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/safestack.h>
#include <openssl/asn1.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include "internal/x509_int.h"
int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len)
{
ASN1_OBJECT *obj;
obj = OBJ_nid2obj(nid);
if (obj == NULL)
return -1;
return X509_NAME_get_text_by_OBJ(name, obj, buf, len);
}
int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj,
char *buf, int len)
{
int i;
const ASN1_STRING *data;
i = X509_NAME_get_index_by_OBJ(name, obj, -1);
if (i < 0)
return -1;
data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
if (buf == NULL)
return data->length;
if (len <= 0)
return 0;
i = (data->length > (len - 1)) ? (len - 1) : data->length;
memcpy(buf, data->data, i);
buf[i] = '\0';
return i;
}
int X509_NAME_entry_count(const X509_NAME *name)
{
if (name == NULL)
return 0;
return sk_X509_NAME_ENTRY_num(name->entries);
}
int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos)
{
ASN1_OBJECT *obj;
obj = OBJ_nid2obj(nid);
if (obj == NULL)
return -2;
return X509_NAME_get_index_by_OBJ(name, obj, lastpos);
}
/* NOTE: you should be passing -1, not 0 as lastpos */
int X509_NAME_get_index_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int lastpos)
{
int n;
X509_NAME_ENTRY *ne;
STACK_OF(X509_NAME_ENTRY) *sk;
if (name == NULL)
return -1;
if (lastpos < 0)
lastpos = -1;
sk = name->entries;
n = sk_X509_NAME_ENTRY_num(sk);
for (lastpos++; lastpos < n; lastpos++) {
ne = sk_X509_NAME_ENTRY_value(sk, lastpos);
if (OBJ_cmp(ne->object, obj) == 0)
return lastpos;
}
return -1;
}
X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, int loc)
{
if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
|| loc < 0)
return NULL;
return sk_X509_NAME_ENTRY_value(name->entries, loc);
}
X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc)
{
X509_NAME_ENTRY *ret;
int i, n, set_prev, set_next;
STACK_OF(X509_NAME_ENTRY) *sk;
if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
|| loc < 0)
return NULL;
sk = name->entries;
ret = sk_X509_NAME_ENTRY_delete(sk, loc);
n = sk_X509_NAME_ENTRY_num(sk);
name->modified = 1;
if (loc == n)
return ret;
/* else we need to fixup the set field */
if (loc != 0)
set_prev = (sk_X509_NAME_ENTRY_value(sk, loc - 1))->set;
else
set_prev = ret->set - 1;
set_next = sk_X509_NAME_ENTRY_value(sk, loc)->set;
/*-
* set_prev is the previous set
* set is the current set
* set_next is the following
* prev 1 1 1 1 1 1 1 1
* set 1 1 2 2
* next 1 1 2 2 2 2 3 2
* so basically only if prev and next differ by 2, then
* re-number down by 1
*/
if (set_prev + 1 < set_next)
for (i = loc; i < n; i++)
sk_X509_NAME_ENTRY_value(sk, i)->set--;
return ret;
}
int X509_NAME_add_entry_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int type,
const unsigned char *bytes, int len, int loc,
int set)
{
X509_NAME_ENTRY *ne;
int ret;
ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len);
if (!ne)
return 0;
ret = X509_NAME_add_entry(name, ne, loc, set);
X509_NAME_ENTRY_free(ne);
return ret;
}
int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
const unsigned char *bytes, int len, int loc,
int set)
{
X509_NAME_ENTRY *ne;
int ret;
ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
if (!ne)
return 0;
ret = X509_NAME_add_entry(name, ne, loc, set);
X509_NAME_ENTRY_free(ne);
return ret;
}
int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
const unsigned char *bytes, int len, int loc,
int set)
{
X509_NAME_ENTRY *ne;
int ret;
ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
if (!ne)
return 0;
ret = X509_NAME_add_entry(name, ne, loc, set);
X509_NAME_ENTRY_free(ne);
return ret;
}
/*
* if set is -1, append to previous set, 0 'a new one', and 1, prepend to the
* guy we are about to stomp on.
*/
int X509_NAME_add_entry(X509_NAME *name, const X509_NAME_ENTRY *ne, int loc,
int set)
{
X509_NAME_ENTRY *new_name = NULL;
int n, i, inc;
STACK_OF(X509_NAME_ENTRY) *sk;
if (name == NULL)
return 0;
sk = name->entries;
n = sk_X509_NAME_ENTRY_num(sk);
if (loc > n)
loc = n;
else if (loc < 0)
loc = n;
inc = (set == 0);
name->modified = 1;
if (set == -1) {
if (loc == 0) {
set = 0;
inc = 1;
} else {
set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set;
}
} else { /* if (set >= 0) */
if (loc >= n) {
if (loc != 0)
set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set + 1;
else
set = 0;
} else
set = sk_X509_NAME_ENTRY_value(sk, loc)->set;
}
/*
* X509_NAME_ENTRY_dup is ASN1 generated code, that can't be easily
* const'ified; harmless cast since dup() don't modify its input.
*/
if ((new_name = X509_NAME_ENTRY_dup((X509_NAME_ENTRY *)ne)) == NULL)
goto err;
new_name->set = set;
if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) {
X509err(X509_F_X509_NAME_ADD_ENTRY, ERR_R_MALLOC_FAILURE);
goto err;
}
if (inc) {
n = sk_X509_NAME_ENTRY_num(sk);
for (i = loc + 1; i < n; i++)
sk_X509_NAME_ENTRY_value(sk, i)->set += 1;
}
return 1;
err:
X509_NAME_ENTRY_free(new_name);
return 0;
}
X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
const char *field, int type,
const unsigned char *bytes,
int len)
{
ASN1_OBJECT *obj;
X509_NAME_ENTRY *nentry;
obj = OBJ_txt2obj(field, 0);
if (obj == NULL) {
X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_TXT,
X509_R_INVALID_FIELD_NAME);
ERR_add_error_data(2, "name=", field);
return NULL;
}
nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
ASN1_OBJECT_free(obj);
return nentry;
}
X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
int type,
const unsigned char *bytes,
int len)
{
ASN1_OBJECT *obj;
X509_NAME_ENTRY *nentry;
obj = OBJ_nid2obj(nid);
if (obj == NULL) {
X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_NID, X509_R_UNKNOWN_NID);
return NULL;
}
nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
ASN1_OBJECT_free(obj);
return nentry;
}
X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
const ASN1_OBJECT *obj, int type,
const unsigned char *bytes,
int len)
{
X509_NAME_ENTRY *ret;
if ((ne == NULL) || (*ne == NULL)) {
if ((ret = X509_NAME_ENTRY_new()) == NULL)
return NULL;
} else
ret = *ne;
if (!X509_NAME_ENTRY_set_object(ret, obj))
goto err;
if (!X509_NAME_ENTRY_set_data(ret, type, bytes, len))
goto err;
if ((ne != NULL) && (*ne == NULL))
*ne = ret;
return ret;
err:
if ((ne == NULL) || (ret != *ne))
X509_NAME_ENTRY_free(ret);
return NULL;
}
int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj)
{
if ((ne == NULL) || (obj == NULL)) {
X509err(X509_F_X509_NAME_ENTRY_SET_OBJECT,
ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
ASN1_OBJECT_free(ne->object);
ne->object = OBJ_dup(obj);
return ((ne->object == NULL) ? 0 : 1);
}
int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
const unsigned char *bytes, int len)
{
int i;
if ((ne == NULL) || ((bytes == NULL) && (len != 0)))
return 0;
if ((type > 0) && (type & MBSTRING_FLAG))
return ASN1_STRING_set_by_NID(&ne->value, bytes,
len, type,
OBJ_obj2nid(ne->object)) ? 1 : 0;
if (len < 0)
len = strlen((const char *)bytes);
i = ASN1_STRING_set(ne->value, bytes, len);
if (!i)
return 0;
if (type != V_ASN1_UNDEF) {
if (type == V_ASN1_APP_CHOOSE)
ne->value->type = ASN1_PRINTABLE_type(bytes, len);
else
ne->value->type = type;
}
return 1;
}
ASN1_OBJECT *X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne)
{
if (ne == NULL)
return NULL;
return ne->object;
}
ASN1_STRING *X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne)
{
if (ne == NULL)
return NULL;
return ne->value;
}
int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne)
{
return ne->set;
}

View file

@ -0,0 +1,40 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include "internal/x509_int.h"
int X509_REQ_set_version(X509_REQ *x, long version)
{
if (x == NULL)
return 0;
x->req_info.enc.modified = 1;
return ASN1_INTEGER_set(x->req_info.version, version);
}
int X509_REQ_set_subject_name(X509_REQ *x, X509_NAME *name)
{
if (x == NULL)
return 0;
x->req_info.enc.modified = 1;
return X509_NAME_set(&x->req_info.subject, name);
}
int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey)
{
if (x == NULL)
return 0;
x->req_info.enc.modified = 1;
return X509_PUBKEY_set(&x->req_info.pubkey, pkey);
}

View file

@ -0,0 +1,75 @@
/*
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/x509.h>
int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey)
{
if ((x == NULL) || (x->spkac == NULL))
return 0;
return X509_PUBKEY_set(&(x->spkac->pubkey), pkey);
}
EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x)
{
if ((x == NULL) || (x->spkac == NULL))
return NULL;
return X509_PUBKEY_get(x->spkac->pubkey);
}
/* Load a Netscape SPKI from a base64 encoded string */
NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, int len)
{
unsigned char *spki_der;
const unsigned char *p;
int spki_len;
NETSCAPE_SPKI *spki;
if (len <= 0)
len = strlen(str);
if ((spki_der = OPENSSL_malloc(len + 1)) == NULL) {
X509err(X509_F_NETSCAPE_SPKI_B64_DECODE, ERR_R_MALLOC_FAILURE);
return NULL;
}
spki_len = EVP_DecodeBlock(spki_der, (const unsigned char *)str, len);
if (spki_len < 0) {
X509err(X509_F_NETSCAPE_SPKI_B64_DECODE, X509_R_BASE64_DECODE_ERROR);
OPENSSL_free(spki_der);
return NULL;
}
p = spki_der;
spki = d2i_NETSCAPE_SPKI(NULL, &p, spki_len);
OPENSSL_free(spki_der);
return spki;
}
/* Generate a base64 encoded string from an SPKI */
char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki)
{
unsigned char *der_spki, *p;
char *b64_str;
int der_len;
der_len = i2d_NETSCAPE_SPKI(spki, NULL);
der_spki = OPENSSL_malloc(der_len);
b64_str = OPENSSL_malloc(der_len * 2);
if (der_spki == NULL || b64_str == NULL) {
X509err(X509_F_NETSCAPE_SPKI_B64_ENCODE, ERR_R_MALLOC_FAILURE);
OPENSSL_free(der_spki);
OPENSSL_free(b64_str);
return NULL;
}
p = der_spki;
i2d_NETSCAPE_SPKI(spki, &p);
EVP_EncodeBlock((unsigned char *)b64_str, der_spki, der_len);
OPENSSL_free(der_spki);
return b64_str;
}

View file

@ -0,0 +1,84 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
int X509_certificate_type(const X509 *x, const EVP_PKEY *pkey)
{
const EVP_PKEY *pk;
int ret = 0, i;
if (x == NULL)
return 0;
if (pkey == NULL)
pk = X509_get0_pubkey(x);
else
pk = pkey;
if (pk == NULL)
return 0;
switch (EVP_PKEY_id(pk)) {
case EVP_PKEY_RSA:
ret = EVP_PK_RSA | EVP_PKT_SIGN;
/* if (!sign only extension) */
ret |= EVP_PKT_ENC;
break;
case EVP_PKEY_RSA_PSS:
ret = EVP_PK_RSA | EVP_PKT_SIGN;
break;
case EVP_PKEY_DSA:
ret = EVP_PK_DSA | EVP_PKT_SIGN;
break;
case EVP_PKEY_EC:
ret = EVP_PK_EC | EVP_PKT_SIGN | EVP_PKT_EXCH;
break;
case EVP_PKEY_ED448:
case EVP_PKEY_ED25519:
ret = EVP_PKT_SIGN;
break;
case EVP_PKEY_DH:
ret = EVP_PK_DH | EVP_PKT_EXCH;
break;
case NID_id_GostR3410_2001:
case NID_id_GostR3410_2012_256:
case NID_id_GostR3410_2012_512:
ret = EVP_PKT_EXCH | EVP_PKT_SIGN;
break;
default:
break;
}
i = X509_get_signature_nid(x);
if (i && OBJ_find_sigid_algs(i, NULL, &i)) {
switch (i) {
case NID_rsaEncryption:
case NID_rsa:
ret |= EVP_PKS_RSA;
break;
case NID_dsa:
case NID_dsa_2:
ret |= EVP_PKS_DSA;
break;
case NID_X9_62_id_ecPublicKey:
ret |= EVP_PKS_EC;
break;
default:
break;
}
}
return ret;
}

View file

@ -0,0 +1,525 @@
/*
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/asn1.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include "internal/x509_int.h"
#include <openssl/ocsp.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/x509v3.h>
int X509_verify(X509 *a, EVP_PKEY *r)
{
if (X509_ALGOR_cmp(&a->sig_alg, &a->cert_info.signature))
return 0;
return (ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF), &a->sig_alg,
&a->signature, &a->cert_info, r));
}
int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r)
{
return (ASN1_item_verify(ASN1_ITEM_rptr(X509_REQ_INFO),
&a->sig_alg, a->signature, &a->req_info, r));
}
int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r)
{
return (ASN1_item_verify(ASN1_ITEM_rptr(NETSCAPE_SPKAC),
&a->sig_algor, a->signature, a->spkac, r));
}
int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
{
x->cert_info.enc.modified = 1;
return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CINF), &x->cert_info.signature,
&x->sig_alg, &x->signature, &x->cert_info, pkey,
md));
}
int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx)
{
x->cert_info.enc.modified = 1;
return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF),
&x->cert_info.signature,
&x->sig_alg, &x->signature, &x->cert_info, ctx);
}
#ifndef OPENSSL_NO_OCSP
int X509_http_nbio(OCSP_REQ_CTX *rctx, X509 **pcert)
{
return OCSP_REQ_CTX_nbio_d2i(rctx,
(ASN1_VALUE **)pcert, ASN1_ITEM_rptr(X509));
}
#endif
int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md)
{
return (ASN1_item_sign(ASN1_ITEM_rptr(X509_REQ_INFO), &x->sig_alg, NULL,
x->signature, &x->req_info, pkey, md));
}
int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx)
{
return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_REQ_INFO),
&x->sig_alg, NULL, x->signature, &x->req_info,
ctx);
}
int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md)
{
x->crl.enc.modified = 1;
return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CRL_INFO), &x->crl.sig_alg,
&x->sig_alg, &x->signature, &x->crl, pkey, md));
}
int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx)
{
x->crl.enc.modified = 1;
return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CRL_INFO),
&x->crl.sig_alg, &x->sig_alg, &x->signature,
&x->crl, ctx);
}
#ifndef OPENSSL_NO_OCSP
int X509_CRL_http_nbio(OCSP_REQ_CTX *rctx, X509_CRL **pcrl)
{
return OCSP_REQ_CTX_nbio_d2i(rctx,
(ASN1_VALUE **)pcrl,
ASN1_ITEM_rptr(X509_CRL));
}
#endif
int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md)
{
return (ASN1_item_sign(ASN1_ITEM_rptr(NETSCAPE_SPKAC), &x->sig_algor, NULL,
x->signature, x->spkac, pkey, md));
}
#ifndef OPENSSL_NO_STDIO
X509 *d2i_X509_fp(FILE *fp, X509 **x509)
{
return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509), fp, x509);
}
int i2d_X509_fp(FILE *fp, X509 *x509)
{
return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509), fp, x509);
}
#endif
X509 *d2i_X509_bio(BIO *bp, X509 **x509)
{
return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509), bp, x509);
}
int i2d_X509_bio(BIO *bp, X509 *x509)
{
return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509), bp, x509);
}
#ifndef OPENSSL_NO_STDIO
X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl)
{
return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl);
}
int i2d_X509_CRL_fp(FILE *fp, X509_CRL *crl)
{
return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl);
}
#endif
X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl)
{
return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl);
}
int i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl)
{
return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl);
}
#ifndef OPENSSL_NO_STDIO
PKCS7 *d2i_PKCS7_fp(FILE *fp, PKCS7 **p7)
{
return ASN1_item_d2i_fp(ASN1_ITEM_rptr(PKCS7), fp, p7);
}
int i2d_PKCS7_fp(FILE *fp, PKCS7 *p7)
{
return ASN1_item_i2d_fp(ASN1_ITEM_rptr(PKCS7), fp, p7);
}
#endif
PKCS7 *d2i_PKCS7_bio(BIO *bp, PKCS7 **p7)
{
return ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKCS7), bp, p7);
}
int i2d_PKCS7_bio(BIO *bp, PKCS7 *p7)
{
return ASN1_item_i2d_bio(ASN1_ITEM_rptr(PKCS7), bp, p7);
}
#ifndef OPENSSL_NO_STDIO
X509_REQ *d2i_X509_REQ_fp(FILE *fp, X509_REQ **req)
{
return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_REQ), fp, req);
}
int i2d_X509_REQ_fp(FILE *fp, X509_REQ *req)
{
return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_REQ), fp, req);
}
#endif
X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req)
{
return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_REQ), bp, req);
}
int i2d_X509_REQ_bio(BIO *bp, X509_REQ *req)
{
return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_REQ), bp, req);
}
#ifndef OPENSSL_NO_RSA
# ifndef OPENSSL_NO_STDIO
RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa)
{
return ASN1_item_d2i_fp(ASN1_ITEM_rptr(RSAPrivateKey), fp, rsa);
}
int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa)
{
return ASN1_item_i2d_fp(ASN1_ITEM_rptr(RSAPrivateKey), fp, rsa);
}
RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa)
{
return ASN1_item_d2i_fp(ASN1_ITEM_rptr(RSAPublicKey), fp, rsa);
}
RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa)
{
return ASN1_d2i_fp((void *(*)(void))
RSA_new, (D2I_OF(void)) d2i_RSA_PUBKEY, fp,
(void **)rsa);
}
int i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa)
{
return ASN1_item_i2d_fp(ASN1_ITEM_rptr(RSAPublicKey), fp, rsa);
}
int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa)
{
return ASN1_i2d_fp((I2D_OF(void))i2d_RSA_PUBKEY, fp, rsa);
}
# endif
RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa)
{
return ASN1_item_d2i_bio(ASN1_ITEM_rptr(RSAPrivateKey), bp, rsa);
}
int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa)
{
return ASN1_item_i2d_bio(ASN1_ITEM_rptr(RSAPrivateKey), bp, rsa);
}
RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa)
{
return ASN1_item_d2i_bio(ASN1_ITEM_rptr(RSAPublicKey), bp, rsa);
}
RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa)
{
return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSA_PUBKEY, bp, rsa);
}
int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa)
{
return ASN1_item_i2d_bio(ASN1_ITEM_rptr(RSAPublicKey), bp, rsa);
}
int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa)
{
return ASN1_i2d_bio_of(RSA, i2d_RSA_PUBKEY, bp, rsa);
}
#endif
#ifndef OPENSSL_NO_DSA
# ifndef OPENSSL_NO_STDIO
DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa)
{
return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSAPrivateKey, fp, dsa);
}
int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa)
{
return ASN1_i2d_fp_of_const(DSA, i2d_DSAPrivateKey, fp, dsa);
}
DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa)
{
return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSA_PUBKEY, fp, dsa);
}
int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa)
{
return ASN1_i2d_fp_of(DSA, i2d_DSA_PUBKEY, fp, dsa);
}
# endif
DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa)
{
return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSAPrivateKey, bp, dsa);
}
int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa)
{
return ASN1_i2d_bio_of_const(DSA, i2d_DSAPrivateKey, bp, dsa);
}
DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa)
{
return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSA_PUBKEY, bp, dsa);
}
int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa)
{
return ASN1_i2d_bio_of(DSA, i2d_DSA_PUBKEY, bp, dsa);
}
#endif
#ifndef OPENSSL_NO_EC
# ifndef OPENSSL_NO_STDIO
EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey)
{
return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, fp, eckey);
}
int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey)
{
return ASN1_i2d_fp_of(EC_KEY, i2d_EC_PUBKEY, fp, eckey);
}
EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey)
{
return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, fp, eckey);
}
int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey)
{
return ASN1_i2d_fp_of(EC_KEY, i2d_ECPrivateKey, fp, eckey);
}
# endif
EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey)
{
return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, bp, eckey);
}
int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *ecdsa)
{
return ASN1_i2d_bio_of(EC_KEY, i2d_EC_PUBKEY, bp, ecdsa);
}
EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey)
{
return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, bp, eckey);
}
int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey)
{
return ASN1_i2d_bio_of(EC_KEY, i2d_ECPrivateKey, bp, eckey);
}
#endif
int X509_pubkey_digest(const X509 *data, const EVP_MD *type,
unsigned char *md, unsigned int *len)
{
ASN1_BIT_STRING *key;
key = X509_get0_pubkey_bitstr(data);
if (!key)
return 0;
return EVP_Digest(key->data, key->length, md, len, type, NULL);
}
int X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md,
unsigned int *len)
{
if (type == EVP_sha1() && (data->ex_flags & EXFLAG_SET) != 0) {
/* Asking for SHA1 and we already computed it. */
if (len != NULL)
*len = sizeof(data->sha1_hash);
memcpy(md, data->sha1_hash, sizeof(data->sha1_hash));
return 1;
}
return (ASN1_item_digest
(ASN1_ITEM_rptr(X509), type, (char *)data, md, len));
}
int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type,
unsigned char *md, unsigned int *len)
{
if (type == EVP_sha1() && (data->flags & EXFLAG_SET) != 0) {
/* Asking for SHA1; always computed in CRL d2i. */
if (len != NULL)
*len = sizeof(data->sha1_hash);
memcpy(md, data->sha1_hash, sizeof(data->sha1_hash));
return 1;
}
return (ASN1_item_digest
(ASN1_ITEM_rptr(X509_CRL), type, (char *)data, md, len));
}
int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type,
unsigned char *md, unsigned int *len)
{
return (ASN1_item_digest
(ASN1_ITEM_rptr(X509_REQ), type, (char *)data, md, len));
}
int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type,
unsigned char *md, unsigned int *len)
{
return (ASN1_item_digest
(ASN1_ITEM_rptr(X509_NAME), type, (char *)data, md, len));
}
int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data,
const EVP_MD *type, unsigned char *md,
unsigned int *len)
{
return (ASN1_item_digest(ASN1_ITEM_rptr(PKCS7_ISSUER_AND_SERIAL), type,
(char *)data, md, len));
}
#ifndef OPENSSL_NO_STDIO
X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8)
{
return ASN1_d2i_fp_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, fp, p8);
}
int i2d_PKCS8_fp(FILE *fp, X509_SIG *p8)
{
return ASN1_i2d_fp_of(X509_SIG, i2d_X509_SIG, fp, p8);
}
#endif
X509_SIG *d2i_PKCS8_bio(BIO *bp, X509_SIG **p8)
{
return ASN1_d2i_bio_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, bp, p8);
}
int i2d_PKCS8_bio(BIO *bp, X509_SIG *p8)
{
return ASN1_i2d_bio_of(X509_SIG, i2d_X509_SIG, bp, p8);
}
#ifndef OPENSSL_NO_STDIO
PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,
PKCS8_PRIV_KEY_INFO **p8inf)
{
return ASN1_d2i_fp_of(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_new,
d2i_PKCS8_PRIV_KEY_INFO, fp, p8inf);
}
int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, PKCS8_PRIV_KEY_INFO *p8inf)
{
return ASN1_i2d_fp_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, fp,
p8inf);
}
int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key)
{
PKCS8_PRIV_KEY_INFO *p8inf;
int ret;
p8inf = EVP_PKEY2PKCS8(key);
if (!p8inf)
return 0;
ret = i2d_PKCS8_PRIV_KEY_INFO_fp(fp, p8inf);
PKCS8_PRIV_KEY_INFO_free(p8inf);
return ret;
}
int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey)
{
return ASN1_i2d_fp_of(EVP_PKEY, i2d_PrivateKey, fp, pkey);
}
EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a)
{
return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, fp, a);
}
int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey)
{
return ASN1_i2d_fp_of(EVP_PKEY, i2d_PUBKEY, fp, pkey);
}
EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a)
{
return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, fp, a);
}
#endif
PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,
PKCS8_PRIV_KEY_INFO **p8inf)
{
return ASN1_d2i_bio_of(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_new,
d2i_PKCS8_PRIV_KEY_INFO, bp, p8inf);
}
int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, PKCS8_PRIV_KEY_INFO *p8inf)
{
return ASN1_i2d_bio_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, bp,
p8inf);
}
int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key)
{
PKCS8_PRIV_KEY_INFO *p8inf;
int ret;
p8inf = EVP_PKEY2PKCS8(key);
if (!p8inf)
return 0;
ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf);
PKCS8_PRIV_KEY_INFO_free(p8inf);
return ret;
}
int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey)
{
return ASN1_i2d_bio_of(EVP_PKEY, i2d_PrivateKey, bp, pkey);
}
EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a)
{
return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, bp, a);
}
int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey)
{
return ASN1_i2d_bio_of(EVP_PKEY, i2d_PUBKEY, bp, pkey);
}
EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a)
{
return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, bp, a);
}

View file

@ -0,0 +1,55 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/objects.h>
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include "x509_lcl.h"
/*-
* X509_ATTRIBUTE: this has the following form:
*
* typedef struct x509_attributes_st
* {
* ASN1_OBJECT *object;
* STACK_OF(ASN1_TYPE) *set;
* } X509_ATTRIBUTE;
*
*/
ASN1_SEQUENCE(X509_ATTRIBUTE) = {
ASN1_SIMPLE(X509_ATTRIBUTE, object, ASN1_OBJECT),
ASN1_SET_OF(X509_ATTRIBUTE, set, ASN1_ANY)
} ASN1_SEQUENCE_END(X509_ATTRIBUTE)
IMPLEMENT_ASN1_FUNCTIONS(X509_ATTRIBUTE)
IMPLEMENT_ASN1_DUP_FUNCTION(X509_ATTRIBUTE)
X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value)
{
X509_ATTRIBUTE *ret = NULL;
ASN1_TYPE *val = NULL;
if ((ret = X509_ATTRIBUTE_new()) == NULL)
return NULL;
ret->object = OBJ_nid2obj(nid);
if ((val = ASN1_TYPE_new()) == NULL)
goto err;
if (!sk_ASN1_TYPE_push(ret->set, val))
goto err;
ASN1_TYPE_set(val, atrtype, value);
return ret;
err:
X509_ATTRIBUTE_free(ret);
ASN1_TYPE_free(val);
return NULL;
}

View file

@ -0,0 +1,478 @@
/*
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include "internal/x509_int.h"
#include <openssl/x509v3.h>
#include "x509_lcl.h"
static int X509_REVOKED_cmp(const X509_REVOKED *const *a,
const X509_REVOKED *const *b);
static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp);
ASN1_SEQUENCE(X509_REVOKED) = {
ASN1_EMBED(X509_REVOKED,serialNumber, ASN1_INTEGER),
ASN1_SIMPLE(X509_REVOKED,revocationDate, ASN1_TIME),
ASN1_SEQUENCE_OF_OPT(X509_REVOKED,extensions, X509_EXTENSION)
} ASN1_SEQUENCE_END(X509_REVOKED)
static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r);
static int def_crl_lookup(X509_CRL *crl,
X509_REVOKED **ret, ASN1_INTEGER *serial,
X509_NAME *issuer);
static X509_CRL_METHOD int_crl_meth = {
0,
0, 0,
def_crl_lookup,
def_crl_verify
};
static const X509_CRL_METHOD *default_crl_method = &int_crl_meth;
/*
* The X509_CRL_INFO structure needs a bit of customisation. Since we cache
* the original encoding the signature won't be affected by reordering of the
* revoked field.
*/
static int crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
{
X509_CRL_INFO *a = (X509_CRL_INFO *)*pval;
if (!a || !a->revoked)
return 1;
switch (operation) {
/*
* Just set cmp function here. We don't sort because that would
* affect the output of X509_CRL_print().
*/
case ASN1_OP_D2I_POST:
(void)sk_X509_REVOKED_set_cmp_func(a->revoked, X509_REVOKED_cmp);
break;
}
return 1;
}
ASN1_SEQUENCE_enc(X509_CRL_INFO, enc, crl_inf_cb) = {
ASN1_OPT(X509_CRL_INFO, version, ASN1_INTEGER),
ASN1_EMBED(X509_CRL_INFO, sig_alg, X509_ALGOR),
ASN1_SIMPLE(X509_CRL_INFO, issuer, X509_NAME),
ASN1_SIMPLE(X509_CRL_INFO, lastUpdate, ASN1_TIME),
ASN1_OPT(X509_CRL_INFO, nextUpdate, ASN1_TIME),
ASN1_SEQUENCE_OF_OPT(X509_CRL_INFO, revoked, X509_REVOKED),
ASN1_EXP_SEQUENCE_OF_OPT(X509_CRL_INFO, extensions, X509_EXTENSION, 0)
} ASN1_SEQUENCE_END_enc(X509_CRL_INFO, X509_CRL_INFO)
/*
* Set CRL entry issuer according to CRL certificate issuer extension. Check
* for unhandled critical CRL entry extensions.
*/
static int crl_set_issuers(X509_CRL *crl)
{
int i, j;
GENERAL_NAMES *gens, *gtmp;
STACK_OF(X509_REVOKED) *revoked;
revoked = X509_CRL_get_REVOKED(crl);
gens = NULL;
for (i = 0; i < sk_X509_REVOKED_num(revoked); i++) {
X509_REVOKED *rev = sk_X509_REVOKED_value(revoked, i);
STACK_OF(X509_EXTENSION) *exts;
ASN1_ENUMERATED *reason;
X509_EXTENSION *ext;
gtmp = X509_REVOKED_get_ext_d2i(rev,
NID_certificate_issuer, &j, NULL);
if (!gtmp && (j != -1)) {
crl->flags |= EXFLAG_INVALID;
return 1;
}
if (gtmp) {
gens = gtmp;
if (!crl->issuers) {
crl->issuers = sk_GENERAL_NAMES_new_null();
if (!crl->issuers)
return 0;
}
if (!sk_GENERAL_NAMES_push(crl->issuers, gtmp))
return 0;
}
rev->issuer = gens;
reason = X509_REVOKED_get_ext_d2i(rev, NID_crl_reason, &j, NULL);
if (!reason && (j != -1)) {
crl->flags |= EXFLAG_INVALID;
return 1;
}
if (reason) {
rev->reason = ASN1_ENUMERATED_get(reason);
ASN1_ENUMERATED_free(reason);
} else
rev->reason = CRL_REASON_NONE;
/* Check for critical CRL entry extensions */
exts = rev->extensions;
for (j = 0; j < sk_X509_EXTENSION_num(exts); j++) {
ext = sk_X509_EXTENSION_value(exts, j);
if (X509_EXTENSION_get_critical(ext)) {
if (OBJ_obj2nid(X509_EXTENSION_get_object(ext)) == NID_certificate_issuer)
continue;
crl->flags |= EXFLAG_CRITICAL;
break;
}
}
}
return 1;
}
/*
* The X509_CRL structure needs a bit of customisation. Cache some extensions
* and hash of the whole CRL.
*/
static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
{
X509_CRL *crl = (X509_CRL *)*pval;
STACK_OF(X509_EXTENSION) *exts;
X509_EXTENSION *ext;
int idx;
switch (operation) {
case ASN1_OP_D2I_PRE:
if (crl->meth->crl_free) {
if (!crl->meth->crl_free(crl))
return 0;
}
AUTHORITY_KEYID_free(crl->akid);
ISSUING_DIST_POINT_free(crl->idp);
ASN1_INTEGER_free(crl->crl_number);
ASN1_INTEGER_free(crl->base_crl_number);
sk_GENERAL_NAMES_pop_free(crl->issuers, GENERAL_NAMES_free);
/* fall thru */
case ASN1_OP_NEW_POST:
crl->idp = NULL;
crl->akid = NULL;
crl->flags = 0;
crl->idp_flags = 0;
crl->idp_reasons = CRLDP_ALL_REASONS;
crl->meth = default_crl_method;
crl->meth_data = NULL;
crl->issuers = NULL;
crl->crl_number = NULL;
crl->base_crl_number = NULL;
break;
case ASN1_OP_D2I_POST:
X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL);
crl->idp = X509_CRL_get_ext_d2i(crl,
NID_issuing_distribution_point, NULL,
NULL);
if (crl->idp)
setup_idp(crl, crl->idp);
crl->akid = X509_CRL_get_ext_d2i(crl,
NID_authority_key_identifier, NULL,
NULL);
crl->crl_number = X509_CRL_get_ext_d2i(crl,
NID_crl_number, NULL, NULL);
crl->base_crl_number = X509_CRL_get_ext_d2i(crl,
NID_delta_crl, NULL,
NULL);
/* Delta CRLs must have CRL number */
if (crl->base_crl_number && !crl->crl_number)
crl->flags |= EXFLAG_INVALID;
/*
* See if we have any unhandled critical CRL extensions and indicate
* this in a flag. We only currently handle IDP so anything else
* critical sets the flag. This code accesses the X509_CRL structure
* directly: applications shouldn't do this.
*/
exts = crl->crl.extensions;
for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++) {
int nid;
ext = sk_X509_EXTENSION_value(exts, idx);
nid = OBJ_obj2nid(X509_EXTENSION_get_object(ext));
if (nid == NID_freshest_crl)
crl->flags |= EXFLAG_FRESHEST;
if (X509_EXTENSION_get_critical(ext)) {
/* We handle IDP and deltas */
if ((nid == NID_issuing_distribution_point)
|| (nid == NID_authority_key_identifier)
|| (nid == NID_delta_crl))
continue;
crl->flags |= EXFLAG_CRITICAL;
break;
}
}
if (!crl_set_issuers(crl))
return 0;
if (crl->meth->crl_init) {
if (crl->meth->crl_init(crl) == 0)
return 0;
}
crl->flags |= EXFLAG_SET;
break;
case ASN1_OP_FREE_POST:
if (crl->meth->crl_free) {
if (!crl->meth->crl_free(crl))
return 0;
}
AUTHORITY_KEYID_free(crl->akid);
ISSUING_DIST_POINT_free(crl->idp);
ASN1_INTEGER_free(crl->crl_number);
ASN1_INTEGER_free(crl->base_crl_number);
sk_GENERAL_NAMES_pop_free(crl->issuers, GENERAL_NAMES_free);
break;
}
return 1;
}
/* Convert IDP into a more convenient form */
static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp)
{
int idp_only = 0;
/* Set various flags according to IDP */
crl->idp_flags |= IDP_PRESENT;
if (idp->onlyuser > 0) {
idp_only++;
crl->idp_flags |= IDP_ONLYUSER;
}
if (idp->onlyCA > 0) {
idp_only++;
crl->idp_flags |= IDP_ONLYCA;
}
if (idp->onlyattr > 0) {
idp_only++;
crl->idp_flags |= IDP_ONLYATTR;
}
if (idp_only > 1)
crl->idp_flags |= IDP_INVALID;
if (idp->indirectCRL > 0)
crl->idp_flags |= IDP_INDIRECT;
if (idp->onlysomereasons) {
crl->idp_flags |= IDP_REASONS;
if (idp->onlysomereasons->length > 0)
crl->idp_reasons = idp->onlysomereasons->data[0];
if (idp->onlysomereasons->length > 1)
crl->idp_reasons |= (idp->onlysomereasons->data[1] << 8);
crl->idp_reasons &= CRLDP_ALL_REASONS;
}
DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl));
}
ASN1_SEQUENCE_ref(X509_CRL, crl_cb) = {
ASN1_EMBED(X509_CRL, crl, X509_CRL_INFO),
ASN1_EMBED(X509_CRL, sig_alg, X509_ALGOR),
ASN1_EMBED(X509_CRL, signature, ASN1_BIT_STRING)
} ASN1_SEQUENCE_END_ref(X509_CRL, X509_CRL)
IMPLEMENT_ASN1_FUNCTIONS(X509_REVOKED)
IMPLEMENT_ASN1_DUP_FUNCTION(X509_REVOKED)
IMPLEMENT_ASN1_FUNCTIONS(X509_CRL_INFO)
IMPLEMENT_ASN1_FUNCTIONS(X509_CRL)
IMPLEMENT_ASN1_DUP_FUNCTION(X509_CRL)
static int X509_REVOKED_cmp(const X509_REVOKED *const *a,
const X509_REVOKED *const *b)
{
return (ASN1_STRING_cmp((ASN1_STRING *)&(*a)->serialNumber,
(ASN1_STRING *)&(*b)->serialNumber));
}
int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev)
{
X509_CRL_INFO *inf;
inf = &crl->crl;
if (inf->revoked == NULL)
inf->revoked = sk_X509_REVOKED_new(X509_REVOKED_cmp);
if (inf->revoked == NULL || !sk_X509_REVOKED_push(inf->revoked, rev)) {
ASN1err(ASN1_F_X509_CRL_ADD0_REVOKED, ERR_R_MALLOC_FAILURE);
return 0;
}
inf->enc.modified = 1;
return 1;
}
int X509_CRL_verify(X509_CRL *crl, EVP_PKEY *r)
{
if (crl->meth->crl_verify)
return crl->meth->crl_verify(crl, r);
return 0;
}
int X509_CRL_get0_by_serial(X509_CRL *crl,
X509_REVOKED **ret, ASN1_INTEGER *serial)
{
if (crl->meth->crl_lookup)
return crl->meth->crl_lookup(crl, ret, serial, NULL);
return 0;
}
int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x)
{
if (crl->meth->crl_lookup)
return crl->meth->crl_lookup(crl, ret,
X509_get_serialNumber(x),
X509_get_issuer_name(x));
return 0;
}
static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r)
{
return (ASN1_item_verify(ASN1_ITEM_rptr(X509_CRL_INFO),
&crl->sig_alg, &crl->signature, &crl->crl, r));
}
static int crl_revoked_issuer_match(X509_CRL *crl, X509_NAME *nm,
X509_REVOKED *rev)
{
int i;
if (!rev->issuer) {
if (!nm)
return 1;
if (!X509_NAME_cmp(nm, X509_CRL_get_issuer(crl)))
return 1;
return 0;
}
if (!nm)
nm = X509_CRL_get_issuer(crl);
for (i = 0; i < sk_GENERAL_NAME_num(rev->issuer); i++) {
GENERAL_NAME *gen = sk_GENERAL_NAME_value(rev->issuer, i);
if (gen->type != GEN_DIRNAME)
continue;
if (!X509_NAME_cmp(nm, gen->d.directoryName))
return 1;
}
return 0;
}
static int def_crl_lookup(X509_CRL *crl,
X509_REVOKED **ret, ASN1_INTEGER *serial,
X509_NAME *issuer)
{
X509_REVOKED rtmp, *rev;
int idx, num;
if (crl->crl.revoked == NULL)
return 0;
/*
* Sort revoked into serial number order if not already sorted. Do this
* under a lock to avoid race condition.
*/
if (!sk_X509_REVOKED_is_sorted(crl->crl.revoked)) {
CRYPTO_THREAD_write_lock(crl->lock);
sk_X509_REVOKED_sort(crl->crl.revoked);
CRYPTO_THREAD_unlock(crl->lock);
}
rtmp.serialNumber = *serial;
idx = sk_X509_REVOKED_find(crl->crl.revoked, &rtmp);
if (idx < 0)
return 0;
/* Need to look for matching name */
for (num = sk_X509_REVOKED_num(crl->crl.revoked); idx < num; idx++) {
rev = sk_X509_REVOKED_value(crl->crl.revoked, idx);
if (ASN1_INTEGER_cmp(&rev->serialNumber, serial))
return 0;
if (crl_revoked_issuer_match(crl, issuer, rev)) {
if (ret)
*ret = rev;
if (rev->reason == CRL_REASON_REMOVE_FROM_CRL)
return 2;
return 1;
}
}
return 0;
}
void X509_CRL_set_default_method(const X509_CRL_METHOD *meth)
{
if (meth == NULL)
default_crl_method = &int_crl_meth;
else
default_crl_method = meth;
}
X509_CRL_METHOD *X509_CRL_METHOD_new(int (*crl_init) (X509_CRL *crl),
int (*crl_free) (X509_CRL *crl),
int (*crl_lookup) (X509_CRL *crl,
X509_REVOKED **ret,
ASN1_INTEGER *ser,
X509_NAME *issuer),
int (*crl_verify) (X509_CRL *crl,
EVP_PKEY *pk))
{
X509_CRL_METHOD *m = OPENSSL_malloc(sizeof(*m));
if (m == NULL) {
X509err(X509_F_X509_CRL_METHOD_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
m->crl_init = crl_init;
m->crl_free = crl_free;
m->crl_lookup = crl_lookup;
m->crl_verify = crl_verify;
m->flags = X509_CRL_METHOD_DYNAMIC;
return m;
}
void X509_CRL_METHOD_free(X509_CRL_METHOD *m)
{
if (m == NULL || !(m->flags & X509_CRL_METHOD_DYNAMIC))
return;
OPENSSL_free(m);
}
void X509_CRL_set_meth_data(X509_CRL *crl, void *dat)
{
crl->meth_data = dat;
}
void *X509_CRL_get_meth_data(X509_CRL *crl)
{
return crl->meth_data;
}

View file

@ -0,0 +1,28 @@
/*
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stddef.h>
#include <openssl/x509.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include "x509_lcl.h"
ASN1_SEQUENCE(X509_EXTENSION) = {
ASN1_SIMPLE(X509_EXTENSION, object, ASN1_OBJECT),
ASN1_OPT(X509_EXTENSION, critical, ASN1_BOOLEAN),
ASN1_EMBED(X509_EXTENSION, value, ASN1_OCTET_STRING)
} ASN1_SEQUENCE_END(X509_EXTENSION)
ASN1_ITEM_TEMPLATE(X509_EXTENSIONS) =
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Extension, X509_EXTENSION)
ASN1_ITEM_TEMPLATE_END(X509_EXTENSIONS)
IMPLEMENT_ASN1_FUNCTIONS(X509_EXTENSION)
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_EXTENSIONS, X509_EXTENSIONS, X509_EXTENSIONS)
IMPLEMENT_ASN1_DUP_FUNCTION(X509_EXTENSION)

View file

@ -0,0 +1,551 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/ctype.h"
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include "internal/x509_int.h"
#include "internal/asn1_int.h"
#include "x509_lcl.h"
/*
* Maximum length of X509_NAME: much larger than anything we should
* ever see in practice.
*/
#define X509_NAME_MAX (1024 * 1024)
static int x509_name_ex_d2i(ASN1_VALUE **val,
const unsigned char **in, long len,
const ASN1_ITEM *it,
int tag, int aclass, char opt, ASN1_TLC *ctx);
static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass);
static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it);
static void x509_name_ex_free(ASN1_VALUE **val, const ASN1_ITEM *it);
static int x509_name_encode(X509_NAME *a);
static int x509_name_canon(X509_NAME *a);
static int asn1_string_canon(ASN1_STRING *out, const ASN1_STRING *in);
static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) * intname,
unsigned char **in);
static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval,
int indent,
const char *fname, const ASN1_PCTX *pctx);
ASN1_SEQUENCE(X509_NAME_ENTRY) = {
ASN1_SIMPLE(X509_NAME_ENTRY, object, ASN1_OBJECT),
ASN1_SIMPLE(X509_NAME_ENTRY, value, ASN1_PRINTABLE)
} ASN1_SEQUENCE_END(X509_NAME_ENTRY)
IMPLEMENT_ASN1_FUNCTIONS(X509_NAME_ENTRY)
IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME_ENTRY)
/*
* For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY } so
* declare two template wrappers for this
*/
ASN1_ITEM_TEMPLATE(X509_NAME_ENTRIES) =
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, RDNS, X509_NAME_ENTRY)
static_ASN1_ITEM_TEMPLATE_END(X509_NAME_ENTRIES)
ASN1_ITEM_TEMPLATE(X509_NAME_INTERNAL) =
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Name, X509_NAME_ENTRIES)
static_ASN1_ITEM_TEMPLATE_END(X509_NAME_INTERNAL)
/*
* Normally that's where it would end: we'd have two nested STACK structures
* representing the ASN1. Unfortunately X509_NAME uses a completely different
* form and caches encodings so we have to process the internal form and
* convert to the external form.
*/
static const ASN1_EXTERN_FUNCS x509_name_ff = {
NULL,
x509_name_ex_new,
x509_name_ex_free,
0, /* Default clear behaviour is OK */
x509_name_ex_d2i,
x509_name_ex_i2d,
x509_name_ex_print
};
IMPLEMENT_EXTERN_ASN1(X509_NAME, V_ASN1_SEQUENCE, x509_name_ff)
IMPLEMENT_ASN1_FUNCTIONS(X509_NAME)
IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME)
static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it)
{
X509_NAME *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL)
goto memerr;
if ((ret->entries = sk_X509_NAME_ENTRY_new_null()) == NULL)
goto memerr;
if ((ret->bytes = BUF_MEM_new()) == NULL)
goto memerr;
ret->modified = 1;
*val = (ASN1_VALUE *)ret;
return 1;
memerr:
ASN1err(ASN1_F_X509_NAME_EX_NEW, ERR_R_MALLOC_FAILURE);
if (ret) {
sk_X509_NAME_ENTRY_free(ret->entries);
OPENSSL_free(ret);
}
return 0;
}
static void x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
X509_NAME *a;
if (!pval || !*pval)
return;
a = (X509_NAME *)*pval;
BUF_MEM_free(a->bytes);
sk_X509_NAME_ENTRY_pop_free(a->entries, X509_NAME_ENTRY_free);
OPENSSL_free(a->canon_enc);
OPENSSL_free(a);
*pval = NULL;
}
static void local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY) *ne)
{
sk_X509_NAME_ENTRY_free(ne);
}
static void local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne)
{
sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free);
}
static int x509_name_ex_d2i(ASN1_VALUE **val,
const unsigned char **in, long len,
const ASN1_ITEM *it, int tag, int aclass,
char opt, ASN1_TLC *ctx)
{
const unsigned char *p = *in, *q;
union {
STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
ASN1_VALUE *a;
} intname = {
NULL
};
union {
X509_NAME *x;
ASN1_VALUE *a;
} nm = {
NULL
};
int i, j, ret;
STACK_OF(X509_NAME_ENTRY) *entries;
X509_NAME_ENTRY *entry;
if (len > X509_NAME_MAX)
len = X509_NAME_MAX;
q = p;
/* Get internal representation of Name */
ret = ASN1_item_ex_d2i(&intname.a,
&p, len, ASN1_ITEM_rptr(X509_NAME_INTERNAL),
tag, aclass, opt, ctx);
if (ret <= 0)
return ret;
if (*val)
x509_name_ex_free(val, NULL);
if (!x509_name_ex_new(&nm.a, NULL))
goto err;
/* We've decoded it: now cache encoding */
if (!BUF_MEM_grow(nm.x->bytes, p - q))
goto err;
memcpy(nm.x->bytes->data, q, p - q);
/* Convert internal representation to X509_NAME structure */
for (i = 0; i < sk_STACK_OF_X509_NAME_ENTRY_num(intname.s); i++) {
entries = sk_STACK_OF_X509_NAME_ENTRY_value(intname.s, i);
for (j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) {
entry = sk_X509_NAME_ENTRY_value(entries, j);
entry->set = i;
if (!sk_X509_NAME_ENTRY_push(nm.x->entries, entry))
goto err;
sk_X509_NAME_ENTRY_set(entries, j, NULL);
}
}
ret = x509_name_canon(nm.x);
if (!ret)
goto err;
sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
local_sk_X509_NAME_ENTRY_free);
nm.x->modified = 0;
*val = nm.a;
*in = p;
return ret;
err:
if (nm.x != NULL)
X509_NAME_free(nm.x);
sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
local_sk_X509_NAME_ENTRY_pop_free);
ASN1err(ASN1_F_X509_NAME_EX_D2I, ERR_R_NESTED_ASN1_ERROR);
return 0;
}
static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass)
{
int ret;
X509_NAME *a = (X509_NAME *)*val;
if (a->modified) {
ret = x509_name_encode(a);
if (ret < 0)
return ret;
ret = x509_name_canon(a);
if (ret < 0)
return ret;
}
ret = a->bytes->length;
if (out != NULL) {
memcpy(*out, a->bytes->data, ret);
*out += ret;
}
return ret;
}
static int x509_name_encode(X509_NAME *a)
{
union {
STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
ASN1_VALUE *a;
} intname = {
NULL
};
int len;
unsigned char *p;
STACK_OF(X509_NAME_ENTRY) *entries = NULL;
X509_NAME_ENTRY *entry;
int i, set = -1;
intname.s = sk_STACK_OF_X509_NAME_ENTRY_new_null();
if (!intname.s)
goto memerr;
for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
entry = sk_X509_NAME_ENTRY_value(a->entries, i);
if (entry->set != set) {
entries = sk_X509_NAME_ENTRY_new_null();
if (!entries)
goto memerr;
if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname.s, entries)) {
sk_X509_NAME_ENTRY_free(entries);
goto memerr;
}
set = entry->set;
}
if (!sk_X509_NAME_ENTRY_push(entries, entry))
goto memerr;
}
len = ASN1_item_ex_i2d(&intname.a, NULL,
ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1);
if (!BUF_MEM_grow(a->bytes, len))
goto memerr;
p = (unsigned char *)a->bytes->data;
ASN1_item_ex_i2d(&intname.a,
&p, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1);
sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
local_sk_X509_NAME_ENTRY_free);
a->modified = 0;
return len;
memerr:
sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
local_sk_X509_NAME_ENTRY_free);
ASN1err(ASN1_F_X509_NAME_ENCODE, ERR_R_MALLOC_FAILURE);
return -1;
}
static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval,
int indent,
const char *fname, const ASN1_PCTX *pctx)
{
if (X509_NAME_print_ex(out, (const X509_NAME *)*pval,
indent, pctx->nm_flags) <= 0)
return 0;
return 2;
}
/*
* This function generates the canonical encoding of the Name structure. In
* it all strings are converted to UTF8, leading, trailing and multiple
* spaces collapsed, converted to lower case and the leading SEQUENCE header
* removed. In future we could also normalize the UTF8 too. By doing this
* comparison of Name structures can be rapidly performed by just using
* memcmp() of the canonical encoding. By omitting the leading SEQUENCE name
* constraints of type dirName can also be checked with a simple memcmp().
*/
static int x509_name_canon(X509_NAME *a)
{
unsigned char *p;
STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname;
STACK_OF(X509_NAME_ENTRY) *entries = NULL;
X509_NAME_ENTRY *entry, *tmpentry = NULL;
int i, set = -1, ret = 0, len;
OPENSSL_free(a->canon_enc);
a->canon_enc = NULL;
/* Special case: empty X509_NAME => null encoding */
if (sk_X509_NAME_ENTRY_num(a->entries) == 0) {
a->canon_enclen = 0;
return 1;
}
intname = sk_STACK_OF_X509_NAME_ENTRY_new_null();
if (intname == NULL) {
X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE);
goto err;
}
for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
entry = sk_X509_NAME_ENTRY_value(a->entries, i);
if (entry->set != set) {
entries = sk_X509_NAME_ENTRY_new_null();
if (entries == NULL)
goto err;
if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries)) {
sk_X509_NAME_ENTRY_free(entries);
X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE);
goto err;
}
set = entry->set;
}
tmpentry = X509_NAME_ENTRY_new();
if (tmpentry == NULL) {
X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE);
goto err;
}
tmpentry->object = OBJ_dup(entry->object);
if (tmpentry->object == NULL) {
X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!asn1_string_canon(tmpentry->value, entry->value))
goto err;
if (!sk_X509_NAME_ENTRY_push(entries, tmpentry)) {
X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE);
goto err;
}
tmpentry = NULL;
}
/* Finally generate encoding */
len = i2d_name_canon(intname, NULL);
if (len < 0)
goto err;
a->canon_enclen = len;
p = OPENSSL_malloc(a->canon_enclen);
if (p == NULL) {
X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE);
goto err;
}
a->canon_enc = p;
i2d_name_canon(intname, &p);
ret = 1;
err:
X509_NAME_ENTRY_free(tmpentry);
sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname,
local_sk_X509_NAME_ENTRY_pop_free);
return ret;
}
/* Bitmap of all the types of string that will be canonicalized. */
#define ASN1_MASK_CANON \
(B_ASN1_UTF8STRING | B_ASN1_BMPSTRING | B_ASN1_UNIVERSALSTRING \
| B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_IA5STRING \
| B_ASN1_VISIBLESTRING)
static int asn1_string_canon(ASN1_STRING *out, const ASN1_STRING *in)
{
unsigned char *to, *from;
int len, i;
/* If type not in bitmask just copy string across */
if (!(ASN1_tag2bit(in->type) & ASN1_MASK_CANON)) {
if (!ASN1_STRING_copy(out, in))
return 0;
return 1;
}
out->type = V_ASN1_UTF8STRING;
out->length = ASN1_STRING_to_UTF8(&out->data, in);
if (out->length == -1)
return 0;
to = out->data;
from = to;
len = out->length;
/*
* Convert string in place to canonical form. Ultimately we may need to
* handle a wider range of characters but for now ignore anything with
* MSB set and rely on the ossl_isspace() to fail on bad characters without
* needing isascii or range checks as well.
*/
/* Ignore leading spaces */
while (len > 0 && ossl_isspace(*from)) {
from++;
len--;
}
to = from + len;
/* Ignore trailing spaces */
while (len > 0 && ossl_isspace(to[-1])) {
to--;
len--;
}
to = out->data;
i = 0;
while (i < len) {
/* If not ASCII set just copy across */
if (!ossl_isascii(*from)) {
*to++ = *from++;
i++;
}
/* Collapse multiple spaces */
else if (ossl_isspace(*from)) {
/* Copy one space across */
*to++ = ' ';
/*
* Ignore subsequent spaces. Note: don't need to check len here
* because we know the last character is a non-space so we can't
* overflow.
*/
do {
from++;
i++;
}
while (ossl_isspace(*from));
} else {
*to++ = ossl_tolower(*from);
from++;
i++;
}
}
out->length = to - out->data;
return 1;
}
static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) * _intname,
unsigned char **in)
{
int i, len, ltmp;
ASN1_VALUE *v;
STACK_OF(ASN1_VALUE) *intname = (STACK_OF(ASN1_VALUE) *)_intname;
len = 0;
for (i = 0; i < sk_ASN1_VALUE_num(intname); i++) {
v = sk_ASN1_VALUE_value(intname, i);
ltmp = ASN1_item_ex_i2d(&v, in,
ASN1_ITEM_rptr(X509_NAME_ENTRIES), -1, -1);
if (ltmp < 0)
return ltmp;
len += ltmp;
}
return len;
}
int X509_NAME_set(X509_NAME **xn, X509_NAME *name)
{
if (*xn == name)
return *xn != NULL;
if ((name = X509_NAME_dup(name)) == NULL)
return 0;
X509_NAME_free(*xn);
*xn = name;
return 1;
}
int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase)
{
char *s, *c, *b;
int l, i;
l = 80 - 2 - obase;
b = X509_NAME_oneline(name, NULL, 0);
if (!b)
return 0;
if (!*b) {
OPENSSL_free(b);
return 1;
}
s = b + 1; /* skip the first slash */
c = s;
for (;;) {
if (((*s == '/') &&
(ossl_isupper(s[1]) && ((s[2] == '=') ||
(ossl_isupper(s[2]) && (s[3] == '='))
))) || (*s == '\0'))
{
i = s - c;
if (BIO_write(bp, c, i) != i)
goto err;
c = s + 1; /* skip following slash */
if (*s != '\0') {
if (BIO_write(bp, ", ", 2) != 2)
goto err;
}
l--;
}
if (*s == '\0')
break;
s++;
l--;
}
OPENSSL_free(b);
return 1;
err:
X509err(X509_F_X509_NAME_PRINT, ERR_R_BUF_LIB);
OPENSSL_free(b);
return 0;
}
int X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder,
size_t *pderlen)
{
/* Make sure encoding is valid */
if (i2d_X509_NAME(nm, NULL) <= 0)
return 0;
if (pder != NULL)
*pder = (unsigned char *)nm->bytes->data;
if (pderlen != NULL)
*pderlen = nm->bytes->length;
return 1;
}

View file

@ -0,0 +1,375 @@
/*
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include "internal/asn1_int.h"
#include "internal/evp_int.h"
#include "internal/x509_int.h"
#include <openssl/rsa.h>
#include <openssl/dsa.h>
struct X509_pubkey_st {
X509_ALGOR *algor;
ASN1_BIT_STRING *public_key;
EVP_PKEY *pkey;
};
static int x509_pubkey_decode(EVP_PKEY **pk, X509_PUBKEY *key);
/* Minor tweak to operation: free up EVP_PKEY */
static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
{
if (operation == ASN1_OP_FREE_POST) {
X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
EVP_PKEY_free(pubkey->pkey);
} else if (operation == ASN1_OP_D2I_POST) {
/* Attempt to decode public key and cache in pubkey structure. */
X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
EVP_PKEY_free(pubkey->pkey);
pubkey->pkey = NULL;
/*
* Opportunistically decode the key but remove any non fatal errors
* from the queue. Subsequent explicit attempts to decode/use the key
* will return an appropriate error.
*/
ERR_set_mark();
if (x509_pubkey_decode(&pubkey->pkey, pubkey) == -1)
return 0;
ERR_pop_to_mark();
}
return 1;
}
ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = {
ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR),
ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING)
} ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY)
IMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY)
int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
{
X509_PUBKEY *pk = NULL;
if (x == NULL)
return 0;
if ((pk = X509_PUBKEY_new()) == NULL)
goto error;
if (pkey->ameth) {
if (pkey->ameth->pub_encode) {
if (!pkey->ameth->pub_encode(pk, pkey)) {
X509err(X509_F_X509_PUBKEY_SET,
X509_R_PUBLIC_KEY_ENCODE_ERROR);
goto error;
}
} else {
X509err(X509_F_X509_PUBKEY_SET, X509_R_METHOD_NOT_SUPPORTED);
goto error;
}
} else {
X509err(X509_F_X509_PUBKEY_SET, X509_R_UNSUPPORTED_ALGORITHM);
goto error;
}
X509_PUBKEY_free(*x);
*x = pk;
pk->pkey = pkey;
EVP_PKEY_up_ref(pkey);
return 1;
error:
X509_PUBKEY_free(pk);
return 0;
}
/*
* Attempt to decode a public key.
* Returns 1 on success, 0 for a decode failure and -1 for a fatal
* error e.g. malloc failure.
*/
static int x509_pubkey_decode(EVP_PKEY **ppkey, X509_PUBKEY *key)
{
EVP_PKEY *pkey = EVP_PKEY_new();
if (pkey == NULL) {
X509err(X509_F_X509_PUBKEY_DECODE, ERR_R_MALLOC_FAILURE);
return -1;
}
if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(key->algor->algorithm))) {
X509err(X509_F_X509_PUBKEY_DECODE, X509_R_UNSUPPORTED_ALGORITHM);
goto error;
}
if (pkey->ameth->pub_decode) {
/*
* Treat any failure of pub_decode as a decode error. In
* future we could have different return codes for decode
* errors and fatal errors such as malloc failure.
*/
if (!pkey->ameth->pub_decode(pkey, key)) {
X509err(X509_F_X509_PUBKEY_DECODE, X509_R_PUBLIC_KEY_DECODE_ERROR);
goto error;
}
} else {
X509err(X509_F_X509_PUBKEY_DECODE, X509_R_METHOD_NOT_SUPPORTED);
goto error;
}
*ppkey = pkey;
return 1;
error:
EVP_PKEY_free(pkey);
return 0;
}
EVP_PKEY *X509_PUBKEY_get0(X509_PUBKEY *key)
{
EVP_PKEY *ret = NULL;
if (key == NULL || key->public_key == NULL)
return NULL;
if (key->pkey != NULL)
return key->pkey;
/*
* When the key ASN.1 is initially parsed an attempt is made to
* decode the public key and cache the EVP_PKEY structure. If this
* operation fails the cached value will be NULL. Parsing continues
* to allow parsing of unknown key types or unsupported forms.
* We repeat the decode operation so the appropriate errors are left
* in the queue.
*/
x509_pubkey_decode(&ret, key);
/* If decode doesn't fail something bad happened */
if (ret != NULL) {
X509err(X509_F_X509_PUBKEY_GET0, ERR_R_INTERNAL_ERROR);
EVP_PKEY_free(ret);
}
return NULL;
}
EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
{
EVP_PKEY *ret = X509_PUBKEY_get0(key);
if (ret != NULL)
EVP_PKEY_up_ref(ret);
return ret;
}
/*
* Now two pseudo ASN1 routines that take an EVP_PKEY structure and encode or
* decode as X509_PUBKEY
*/
EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length)
{
X509_PUBKEY *xpk;
EVP_PKEY *pktmp;
const unsigned char *q;
q = *pp;
xpk = d2i_X509_PUBKEY(NULL, &q, length);
if (!xpk)
return NULL;
pktmp = X509_PUBKEY_get(xpk);
X509_PUBKEY_free(xpk);
if (!pktmp)
return NULL;
*pp = q;
if (a) {
EVP_PKEY_free(*a);
*a = pktmp;
}
return pktmp;
}
int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp)
{
X509_PUBKEY *xpk = NULL;
int ret;
if (!a)
return 0;
if (!X509_PUBKEY_set(&xpk, a))
return -1;
ret = i2d_X509_PUBKEY(xpk, pp);
X509_PUBKEY_free(xpk);
return ret;
}
/*
* The following are equivalents but which return RSA and DSA keys
*/
#ifndef OPENSSL_NO_RSA
RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length)
{
EVP_PKEY *pkey;
RSA *key;
const unsigned char *q;
q = *pp;
pkey = d2i_PUBKEY(NULL, &q, length);
if (!pkey)
return NULL;
key = EVP_PKEY_get1_RSA(pkey);
EVP_PKEY_free(pkey);
if (!key)
return NULL;
*pp = q;
if (a) {
RSA_free(*a);
*a = key;
}
return key;
}
int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp)
{
EVP_PKEY *pktmp;
int ret;
if (!a)
return 0;
pktmp = EVP_PKEY_new();
if (pktmp == NULL) {
ASN1err(ASN1_F_I2D_RSA_PUBKEY, ERR_R_MALLOC_FAILURE);
return -1;
}
EVP_PKEY_set1_RSA(pktmp, a);
ret = i2d_PUBKEY(pktmp, pp);
EVP_PKEY_free(pktmp);
return ret;
}
#endif
#ifndef OPENSSL_NO_DSA
DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length)
{
EVP_PKEY *pkey;
DSA *key;
const unsigned char *q;
q = *pp;
pkey = d2i_PUBKEY(NULL, &q, length);
if (!pkey)
return NULL;
key = EVP_PKEY_get1_DSA(pkey);
EVP_PKEY_free(pkey);
if (!key)
return NULL;
*pp = q;
if (a) {
DSA_free(*a);
*a = key;
}
return key;
}
int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp)
{
EVP_PKEY *pktmp;
int ret;
if (!a)
return 0;
pktmp = EVP_PKEY_new();
if (pktmp == NULL) {
ASN1err(ASN1_F_I2D_DSA_PUBKEY, ERR_R_MALLOC_FAILURE);
return -1;
}
EVP_PKEY_set1_DSA(pktmp, a);
ret = i2d_PUBKEY(pktmp, pp);
EVP_PKEY_free(pktmp);
return ret;
}
#endif
#ifndef OPENSSL_NO_EC
EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
{
EVP_PKEY *pkey;
EC_KEY *key;
const unsigned char *q;
q = *pp;
pkey = d2i_PUBKEY(NULL, &q, length);
if (!pkey)
return NULL;
key = EVP_PKEY_get1_EC_KEY(pkey);
EVP_PKEY_free(pkey);
if (!key)
return NULL;
*pp = q;
if (a) {
EC_KEY_free(*a);
*a = key;
}
return key;
}
int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp)
{
EVP_PKEY *pktmp;
int ret;
if (!a)
return 0;
if ((pktmp = EVP_PKEY_new()) == NULL) {
ASN1err(ASN1_F_I2D_EC_PUBKEY, ERR_R_MALLOC_FAILURE);
return -1;
}
EVP_PKEY_set1_EC_KEY(pktmp, a);
ret = i2d_PUBKEY(pktmp, pp);
EVP_PKEY_free(pktmp);
return ret;
}
#endif
int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj,
int ptype, void *pval,
unsigned char *penc, int penclen)
{
if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval))
return 0;
if (penc) {
OPENSSL_free(pub->public_key->data);
pub->public_key->data = penc;
pub->public_key->length = penclen;
/* Set number of unused bits to zero */
pub->public_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT;
}
return 1;
}
int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg,
const unsigned char **pk, int *ppklen,
X509_ALGOR **pa, X509_PUBKEY *pub)
{
if (ppkalg)
*ppkalg = pub->algor->algorithm;
if (pk) {
*pk = pub->public_key->data;
*ppklen = pub->public_key->length;
}
if (pa)
*pa = pub->algor;
return 1;
}
ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x)
{
if (x == NULL)
return NULL;
return x->cert_info.key->public_key;
}

View file

@ -0,0 +1,68 @@
/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include "internal/x509_int.h"
/*-
* X509_REQ_INFO is handled in an unusual way to get round
* invalid encodings. Some broken certificate requests don't
* encode the attributes field if it is empty. This is in
* violation of PKCS#10 but we need to tolerate it. We do
* this by making the attributes field OPTIONAL then using
* the callback to initialise it to an empty STACK.
*
* This means that the field will be correctly encoded unless
* we NULL out the field.
*
* As a result we no longer need the req_kludge field because
* the information is now contained in the attributes field:
* 1. If it is NULL then it's the invalid omission.
* 2. If it is empty it is the correct encoding.
* 3. If it is not empty then some attributes are present.
*
*/
static int rinf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
{
X509_REQ_INFO *rinf = (X509_REQ_INFO *)*pval;
if (operation == ASN1_OP_NEW_POST) {
rinf->attributes = sk_X509_ATTRIBUTE_new_null();
if (!rinf->attributes)
return 0;
}
return 1;
}
ASN1_SEQUENCE_enc(X509_REQ_INFO, enc, rinf_cb) = {
ASN1_SIMPLE(X509_REQ_INFO, version, ASN1_INTEGER),
ASN1_SIMPLE(X509_REQ_INFO, subject, X509_NAME),
ASN1_SIMPLE(X509_REQ_INFO, pubkey, X509_PUBKEY),
/* This isn't really OPTIONAL but it gets round invalid
* encodings
*/
ASN1_IMP_SET_OF_OPT(X509_REQ_INFO, attributes, X509_ATTRIBUTE, 0)
} ASN1_SEQUENCE_END_enc(X509_REQ_INFO, X509_REQ_INFO)
IMPLEMENT_ASN1_FUNCTIONS(X509_REQ_INFO)
ASN1_SEQUENCE_ref(X509_REQ, 0) = {
ASN1_EMBED(X509_REQ, req_info, X509_REQ_INFO),
ASN1_EMBED(X509_REQ, sig_alg, X509_ALGOR),
ASN1_SIMPLE(X509_REQ, signature, ASN1_BIT_STRING)
} ASN1_SEQUENCE_END_ref(X509_REQ, X509_REQ)
IMPLEMENT_ASN1_FUNCTIONS(X509_REQ)
IMPLEMENT_ASN1_DUP_FUNCTION(X509_REQ)

View file

@ -0,0 +1,247 @@
/*
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "internal/x509_int.h"
ASN1_SEQUENCE_enc(X509_CINF, enc, 0) = {
ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0),
ASN1_EMBED(X509_CINF, serialNumber, ASN1_INTEGER),
ASN1_EMBED(X509_CINF, signature, X509_ALGOR),
ASN1_SIMPLE(X509_CINF, issuer, X509_NAME),
ASN1_EMBED(X509_CINF, validity, X509_VAL),
ASN1_SIMPLE(X509_CINF, subject, X509_NAME),
ASN1_SIMPLE(X509_CINF, key, X509_PUBKEY),
ASN1_IMP_OPT(X509_CINF, issuerUID, ASN1_BIT_STRING, 1),
ASN1_IMP_OPT(X509_CINF, subjectUID, ASN1_BIT_STRING, 2),
ASN1_EXP_SEQUENCE_OF_OPT(X509_CINF, extensions, X509_EXTENSION, 3)
} ASN1_SEQUENCE_END_enc(X509_CINF, X509_CINF)
IMPLEMENT_ASN1_FUNCTIONS(X509_CINF)
/* X509 top level structure needs a bit of customisation */
extern void policy_cache_free(X509_POLICY_CACHE *cache);
static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
{
X509 *ret = (X509 *)*pval;
switch (operation) {
case ASN1_OP_D2I_PRE:
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data);
X509_CERT_AUX_free(ret->aux);
ASN1_OCTET_STRING_free(ret->skid);
AUTHORITY_KEYID_free(ret->akid);
CRL_DIST_POINTS_free(ret->crldp);
policy_cache_free(ret->policy_cache);
GENERAL_NAMES_free(ret->altname);
NAME_CONSTRAINTS_free(ret->nc);
#ifndef OPENSSL_NO_RFC3779
sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free);
ASIdentifiers_free(ret->rfc3779_asid);
#endif
/* fall thru */
case ASN1_OP_NEW_POST:
ret->ex_cached = 0;
ret->ex_kusage = 0;
ret->ex_xkusage = 0;
ret->ex_nscert = 0;
ret->ex_flags = 0;
ret->ex_pathlen = -1;
ret->ex_pcpathlen = -1;
ret->skid = NULL;
ret->akid = NULL;
ret->policy_cache = NULL;
ret->altname = NULL;
ret->nc = NULL;
#ifndef OPENSSL_NO_RFC3779
ret->rfc3779_addr = NULL;
ret->rfc3779_asid = NULL;
#endif
ret->aux = NULL;
ret->crldp = NULL;
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data))
return 0;
break;
case ASN1_OP_FREE_POST:
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data);
X509_CERT_AUX_free(ret->aux);
ASN1_OCTET_STRING_free(ret->skid);
AUTHORITY_KEYID_free(ret->akid);
CRL_DIST_POINTS_free(ret->crldp);
policy_cache_free(ret->policy_cache);
GENERAL_NAMES_free(ret->altname);
NAME_CONSTRAINTS_free(ret->nc);
#ifndef OPENSSL_NO_RFC3779
sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free);
ASIdentifiers_free(ret->rfc3779_asid);
#endif
break;
}
return 1;
}
ASN1_SEQUENCE_ref(X509, x509_cb) = {
ASN1_EMBED(X509, cert_info, X509_CINF),
ASN1_EMBED(X509, sig_alg, X509_ALGOR),
ASN1_EMBED(X509, signature, ASN1_BIT_STRING)
} ASN1_SEQUENCE_END_ref(X509, X509)
IMPLEMENT_ASN1_FUNCTIONS(X509)
IMPLEMENT_ASN1_DUP_FUNCTION(X509)
int X509_set_ex_data(X509 *r, int idx, void *arg)
{
return CRYPTO_set_ex_data(&r->ex_data, idx, arg);
}
void *X509_get_ex_data(X509 *r, int idx)
{
return CRYPTO_get_ex_data(&r->ex_data, idx);
}
/*
* X509_AUX ASN1 routines. X509_AUX is the name given to a certificate with
* extra info tagged on the end. Since these functions set how a certificate
* is trusted they should only be used when the certificate comes from a
* reliable source such as local storage.
*/
X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length)
{
const unsigned char *q;
X509 *ret;
int freeret = 0;
/* Save start position */
q = *pp;
if (a == NULL || *a == NULL)
freeret = 1;
ret = d2i_X509(a, &q, length);
/* If certificate unreadable then forget it */
if (ret == NULL)
return NULL;
/* update length */
length -= q - *pp;
if (length > 0 && !d2i_X509_CERT_AUX(&ret->aux, &q, length))
goto err;
*pp = q;
return ret;
err:
if (freeret) {
X509_free(ret);
if (a)
*a = NULL;
}
return NULL;
}
/*
* Serialize trusted certificate to *pp or just return the required buffer
* length if pp == NULL. We ultimately want to avoid modifying *pp in the
* error path, but that depends on similar hygiene in lower-level functions.
* Here we avoid compounding the problem.
*/
static int i2d_x509_aux_internal(X509 *a, unsigned char **pp)
{
int length, tmplen;
unsigned char *start = pp != NULL ? *pp : NULL;
/*
* This might perturb *pp on error, but fixing that belongs in i2d_X509()
* not here. It should be that if a == NULL length is zero, but we check
* both just in case.
*/
length = i2d_X509(a, pp);
if (length <= 0 || a == NULL)
return length;
tmplen = i2d_X509_CERT_AUX(a->aux, pp);
if (tmplen < 0) {
if (start != NULL)
*pp = start;
return tmplen;
}
length += tmplen;
return length;
}
/*
* Serialize trusted certificate to *pp, or just return the required buffer
* length if pp == NULL.
*
* When pp is not NULL, but *pp == NULL, we allocate the buffer, but since
* we're writing two ASN.1 objects back to back, we can't have i2d_X509() do
* the allocation, nor can we allow i2d_X509_CERT_AUX() to increment the
* allocated buffer.
*/
int i2d_X509_AUX(X509 *a, unsigned char **pp)
{
int length;
unsigned char *tmp;
/* Buffer provided by caller */
if (pp == NULL || *pp != NULL)
return i2d_x509_aux_internal(a, pp);
/* Obtain the combined length */
if ((length = i2d_x509_aux_internal(a, NULL)) <= 0)
return length;
/* Allocate requisite combined storage */
*pp = tmp = OPENSSL_malloc(length);
if (tmp == NULL) {
X509err(X509_F_I2D_X509_AUX, ERR_R_MALLOC_FAILURE);
return -1;
}
/* Encode, but keep *pp at the originally malloced pointer */
length = i2d_x509_aux_internal(a, &tmp);
if (length <= 0) {
OPENSSL_free(*pp);
*pp = NULL;
}
return length;
}
int i2d_re_X509_tbs(X509 *x, unsigned char **pp)
{
x->cert_info.enc.modified = 1;
return i2d_X509_CINF(&x->cert_info, pp);
}
void X509_get0_signature(const ASN1_BIT_STRING **psig,
const X509_ALGOR **palg, const X509 *x)
{
if (psig)
*psig = &x->signature;
if (palg)
*palg = &x->sig_alg;
}
int X509_get_signature_nid(const X509 *x)
{
return OBJ_obj2nid(x->sig_alg.algorithm);
}

View file

@ -0,0 +1,169 @@
/*
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include "internal/x509_int.h"
/*
* X509_CERT_AUX routines. These are used to encode additional user
* modifiable data about a certificate. This data is appended to the X509
* encoding when the *_X509_AUX routines are used. This means that the
* "traditional" X509 routines will simply ignore the extra data.
*/
static X509_CERT_AUX *aux_get(X509 *x);
ASN1_SEQUENCE(X509_CERT_AUX) = {
ASN1_SEQUENCE_OF_OPT(X509_CERT_AUX, trust, ASN1_OBJECT),
ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, reject, ASN1_OBJECT, 0),
ASN1_OPT(X509_CERT_AUX, alias, ASN1_UTF8STRING),
ASN1_OPT(X509_CERT_AUX, keyid, ASN1_OCTET_STRING),
ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, other, X509_ALGOR, 1)
} ASN1_SEQUENCE_END(X509_CERT_AUX)
IMPLEMENT_ASN1_FUNCTIONS(X509_CERT_AUX)
int X509_trusted(const X509 *x)
{
return x->aux ? 1 : 0;
}
static X509_CERT_AUX *aux_get(X509 *x)
{
if (x == NULL)
return NULL;
if (x->aux == NULL && (x->aux = X509_CERT_AUX_new()) == NULL)
return NULL;
return x->aux;
}
int X509_alias_set1(X509 *x, const unsigned char *name, int len)
{
X509_CERT_AUX *aux;
if (!name) {
if (!x || !x->aux || !x->aux->alias)
return 1;
ASN1_UTF8STRING_free(x->aux->alias);
x->aux->alias = NULL;
return 1;
}
if ((aux = aux_get(x)) == NULL)
return 0;
if (aux->alias == NULL && (aux->alias = ASN1_UTF8STRING_new()) == NULL)
return 0;
return ASN1_STRING_set(aux->alias, name, len);
}
int X509_keyid_set1(X509 *x, const unsigned char *id, int len)
{
X509_CERT_AUX *aux;
if (!id) {
if (!x || !x->aux || !x->aux->keyid)
return 1;
ASN1_OCTET_STRING_free(x->aux->keyid);
x->aux->keyid = NULL;
return 1;
}
if ((aux = aux_get(x)) == NULL)
return 0;
if (aux->keyid == NULL
&& (aux->keyid = ASN1_OCTET_STRING_new()) == NULL)
return 0;
return ASN1_STRING_set(aux->keyid, id, len);
}
unsigned char *X509_alias_get0(X509 *x, int *len)
{
if (!x->aux || !x->aux->alias)
return NULL;
if (len)
*len = x->aux->alias->length;
return x->aux->alias->data;
}
unsigned char *X509_keyid_get0(X509 *x, int *len)
{
if (!x->aux || !x->aux->keyid)
return NULL;
if (len)
*len = x->aux->keyid->length;
return x->aux->keyid->data;
}
int X509_add1_trust_object(X509 *x, const ASN1_OBJECT *obj)
{
X509_CERT_AUX *aux;
ASN1_OBJECT *objtmp = NULL;
if (obj) {
objtmp = OBJ_dup(obj);
if (!objtmp)
return 0;
}
if ((aux = aux_get(x)) == NULL)
goto err;
if (aux->trust == NULL
&& (aux->trust = sk_ASN1_OBJECT_new_null()) == NULL)
goto err;
if (!objtmp || sk_ASN1_OBJECT_push(aux->trust, objtmp))
return 1;
err:
ASN1_OBJECT_free(objtmp);
return 0;
}
int X509_add1_reject_object(X509 *x, const ASN1_OBJECT *obj)
{
X509_CERT_AUX *aux;
ASN1_OBJECT *objtmp;
if ((objtmp = OBJ_dup(obj)) == NULL)
return 0;
if ((aux = aux_get(x)) == NULL)
goto err;
if (aux->reject == NULL
&& (aux->reject = sk_ASN1_OBJECT_new_null()) == NULL)
goto err;
return sk_ASN1_OBJECT_push(aux->reject, objtmp);
err:
ASN1_OBJECT_free(objtmp);
return 0;
}
void X509_trust_clear(X509 *x)
{
if (x->aux) {
sk_ASN1_OBJECT_pop_free(x->aux->trust, ASN1_OBJECT_free);
x->aux->trust = NULL;
}
}
void X509_reject_clear(X509 *x)
{
if (x->aux) {
sk_ASN1_OBJECT_pop_free(x->aux->reject, ASN1_OBJECT_free);
x->aux->reject = NULL;
}
}
STACK_OF(ASN1_OBJECT) *X509_get0_trust_objects(X509 *x)
{
if (x->aux != NULL)
return x->aux->trust;
return NULL;
}
STACK_OF(ASN1_OBJECT) *X509_get0_reject_objects(X509 *x)
{
if (x->aux != NULL)
return x->aux->reject;
return NULL;
}