#include <sys/cdefs.h>
#include <sys/time.h>
#include <stdarg.h>
#define NEED_BRSSL_H
#include "libsecureboot-priv.h"
#include <brssl.h>
#include <ta.h>
#ifndef TRUST_ANCHOR_STR
# define TRUST_ANCHOR_STR ta_PEM
#endif
#define EPOCH_YEAR 1970
#define AVG_SECONDS_PER_YEAR 31556952L
#define SECONDS_PER_DAY 86400
#define SECONDS_PER_YEAR 365 * SECONDS_PER_DAY
#ifndef VE_UTC_MAX_JUMP
# define VE_UTC_MAX_JUMP 20 * SECONDS_PER_YEAR
#endif
#define X509_DAYS_TO_UTC0 719528
int DebugVe = 0;
#ifndef VE_VERIFY_FLAGS
# define VE_VERIFY_FLAGS VEF_VERBOSE
#endif
int VerifyFlags = VE_VERIFY_FLAGS;
typedef VECTOR(br_x509_certificate) cert_list;
typedef VECTOR(hash_data) digest_list;
static anchor_list trust_anchors = VEC_INIT;
static anchor_list forbidden_anchors = VEC_INIT;
static digest_list forbidden_digests = VEC_INIT;
static int anchor_verbose = 0;
void
ve_anchor_verbose_set(int n)
{
anchor_verbose = n;
}
int
ve_anchor_verbose_get(void)
{
return (anchor_verbose);
}
void
ve_debug_set(int n)
{
DebugVe = n;
}
static int enforce_validity = 0;
void
ve_enforce_validity_set(int i)
{
enforce_validity = i;
}
static char ebuf[512];
char *
ve_error_get(void)
{
return (ebuf);
}
int
ve_error_set(const char *fmt, ...)
{
int rc;
va_list ap;
va_start(ap, fmt);
ebuf[0] = '\0';
rc = 0;
if (fmt) {
#ifdef STAND_H
vsprintf(ebuf, fmt, ap);
ebuf[sizeof(ebuf) - 1] = '\0';
rc = strlen(ebuf);
#else
rc = vsnprintf(ebuf, sizeof(ebuf), fmt, ap);
#endif
}
va_end(ap);
return (rc);
}
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
static const char *
gdate(char *buf, size_t bufsz, time_t clock)
{
int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int year, y, m, d;
y = clock / AVG_SECONDS_PER_YEAR;
year = EPOCH_YEAR + y;
for (y = EPOCH_YEAR; y < year; y++) {
clock -= SECONDS_PER_YEAR;
if (isleap(y))
clock -= SECONDS_PER_DAY;
}
d = clock / SECONDS_PER_DAY;
for (m = 0; d > 1 && m < 12; m++) {
if (d > days[m]) {
d -= days[m];
if (m == 1 && d > 0 && isleap(year))
d--;
} else
break;
}
d++;
if (d > days[m]) {
d = 1;
m++;
if (m >= 12) {
year++;
m = 0;
}
}
(void)snprintf(buf, bufsz, "%04d-%02d-%02d", year, m+1, d);
return(buf);
}
#ifdef UNIT_TEST
extern time_t ve_utc;
time_t ve_utc = 0;
#else
static time_t ve_utc = 0;
#endif
void
ve_utc_set(time_t utc)
{
if (utc > ve_utc &&
(ve_utc == 0 || (utc - ve_utc) < VE_UTC_MAX_JUMP)) {
DEBUG_PRINTF(2, ("Set ve_utc=%jd\n", (intmax_t)utc));
ve_utc = utc;
}
}
#ifdef VERIFY_CERTS_STR
static void
free_cert_contents(br_x509_certificate *xc)
{
xfree(xc->data);
}
#endif
static char *
x509_cn_get(br_x509_certificate *xc, char *buf, size_t len)
{
br_x509_minimal_context mc;
br_name_element cn;
unsigned char cn_oid[4];
int err;
if (buf == NULL)
return (buf);
cn_oid[0] = 3;
cn_oid[1] = 0x55;
cn_oid[2] = 4;
cn_oid[3] = 3;
cn.oid = cn_oid;
cn.buf = buf;
cn.len = len;
cn.buf[0] = '\0';
br_x509_minimal_init(&mc, &br_sha256_vtable, NULL, 0);
br_x509_minimal_set_name_elements(&mc, &cn, 1);
mc.vtable->start_chain(&mc.vtable, NULL);
mc.vtable->start_cert(&mc.vtable, xc->data_len);
mc.vtable->append(&mc.vtable, xc->data, xc->data_len);
mc.vtable->end_cert(&mc.vtable);
err = mc.vtable->end_chain(&mc.vtable);
(void)err;
if (cn.status <= 0)
buf = NULL;
return (buf);
}
#define ASN1_PRIMITIVE_TAG 0x1F
#define ASN1_INF_LENGTH 0x80
#define ASN1_LENGTH_MASK 0x7F
static void*
X509_to_tbs(unsigned char* cert, size_t* output_size)
{
unsigned char *result;
size_t tbs_size;
int size, i;
if (cert == NULL)
return (NULL);
for (i = 0; i < 2; i++) {
if ((*cert & ASN1_PRIMITIVE_TAG) == ASN1_PRIMITIVE_TAG)
return (NULL);
cert++;
if (*cert == ASN1_INF_LENGTH)
return (NULL);
size = *cert & ASN1_LENGTH_MASK;
tbs_size = 0;
if (*cert & (ASN1_LENGTH_MASK + 1)) {
cert++;
while (*cert == 0 && size > 0) {
cert++;
size--;
}
while (size-- > 0) {
tbs_size <<= 8;
tbs_size |= *(cert++);
}
}
if (i == 0)
result = cert;
}
tbs_size += (cert - result);
if (output_size != NULL)
*output_size = tbs_size;
return (result);
}
void
ve_forbidden_digest_add(hash_data *digest, size_t num)
{
while (num--)
VEC_ADD(forbidden_digests, digest[num]);
}
static size_t
ve_anchors_add(br_x509_certificate *xcs, size_t num, anchor_list *anchors,
const char *anchors_name)
{
br_x509_trust_anchor ta;
size_t u;
for (u = 0; u < num; u++) {
if (certificate_to_trust_anchor_inner(&ta, &xcs[u]) < 0) {
break;
}
VEC_ADD(*anchors, ta);
if (anchor_verbose && anchors_name) {
char buf[64];
char *cp;
cp = x509_cn_get(&xcs[u], buf, sizeof(buf));
if (cp) {
printf("x509_anchor(%s) %s\n", cp, anchors_name);
}
}
}
return (u);
}
size_t
ve_trust_anchors_add(br_x509_certificate *xcs, size_t num)
{
return (ve_anchors_add(xcs, num, &trust_anchors, "trusted"));
}
size_t
ve_forbidden_anchors_add(br_x509_certificate *xcs, size_t num)
{
return (ve_anchors_add(xcs, num, &forbidden_anchors, "forbidden"));
}
size_t
ve_trust_anchors_add_buf(unsigned char *buf, size_t len)
{
br_x509_certificate *xcs;
size_t num;
num = 0;
if (len > 0) {
xcs = parse_certificates(buf, len, &num);
if (xcs != NULL) {
num = ve_trust_anchors_add(xcs, num);
#ifdef VE_OPENPGP_SUPPORT
} else {
num = openpgp_trust_add_buf(buf, len);
#endif
}
}
return (num);
}
size_t
ve_trust_anchors_revoke(unsigned char *buf, size_t len)
{
br_x509_certificate *xcs;
size_t num;
num = 0;
if (len > 0) {
xcs = parse_certificates(buf, len, &num);
if (xcs != NULL) {
num = ve_forbidden_anchors_add(xcs, num);
#ifdef VE_OPENPGP_SUPPORT
} else {
if (buf[len - 1] == '\n')
buf[len - 1] = '\0';
num = openpgp_trust_revoke((char *)buf);
#endif
}
}
return (num);
}
int
ve_trust_init(void)
{
static int once = -1;
if (once >= 0)
return (once);
once = 0;
#ifdef BUILD_UTC
ve_utc_set(BUILD_UTC);
#endif
ve_utc_set(time(NULL));
ve_error_set(NULL);
#ifdef VE_PCR_SUPPORT
ve_pcr_init();
#endif
#ifdef TRUST_ANCHOR_STR
if (TRUST_ANCHOR_STR != NULL && strlen(TRUST_ANCHOR_STR) != 0ul)
ve_trust_anchors_add_buf(__DECONST(unsigned char *,
TRUST_ANCHOR_STR), sizeof(TRUST_ANCHOR_STR));
#endif
once = (int) VEC_LEN(trust_anchors);
#ifdef VE_OPENPGP_SUPPORT
once += openpgp_trust_init();
#endif
return (once);
}
#ifdef HAVE_BR_X509_TIME_CHECK
static int
verify_time_cb(void *tctx __unused,
uint32_t not_before_days, uint32_t not_before_seconds,
uint32_t not_after_days, uint32_t not_after_seconds)
{
time_t not_before;
time_t not_after;
int rc;
#ifdef UNIT_TEST
char date[12], nb_date[12], na_date[12];
#endif
if (enforce_validity) {
not_before = ((not_before_days - X509_DAYS_TO_UTC0) * SECONDS_PER_DAY) + not_before_seconds;
not_after = ((not_after_days - X509_DAYS_TO_UTC0) * SECONDS_PER_DAY) + not_after_seconds;
if (ve_utc < not_before)
rc = -1;
else if (ve_utc > not_after)
rc = 1;
else
rc = 0;
#ifdef UNIT_TEST
printf("notBefore %s notAfter %s date %s rc %d\n",
gdate(nb_date, sizeof(nb_date), not_before),
gdate(na_date, sizeof(na_date), not_after),
gdate(date, sizeof(date), ve_utc), rc);
#endif
} else
rc = 0;
return rc;
}
#endif
static br_x509_pkey *
verify_signer_xcs(br_x509_certificate *xcs,
size_t num,
br_name_element *elts, size_t num_elts,
anchor_list *anchors)
{
br_x509_minimal_context mc;
br_x509_certificate *xc;
size_t u;
cert_list chain = VEC_INIT;
const br_x509_pkey *tpk;
br_x509_pkey *pk;
unsigned int usages;
int err;
DEBUG_PRINTF(5, ("verify_signer: %zu certs in chain\n", num));
VEC_ADDMANY(chain, xcs, num);
if (VEC_LEN(chain) == 0) {
ve_error_set("ERROR: no/invalid certificate chain\n");
return (NULL);
}
DEBUG_PRINTF(5, ("verify_signer: %zu trust anchors\n",
VEC_LEN(*anchors)));
br_x509_minimal_init(&mc, &br_sha256_vtable,
&VEC_ELT(*anchors, 0),
VEC_LEN(*anchors));
#ifdef VE_ECDSA_SUPPORT
br_x509_minimal_set_ecdsa(&mc,
&br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
#endif
#ifdef VE_RSA_SUPPORT
br_x509_minimal_set_rsa(&mc, &br_rsa_i31_pkcs1_vrfy);
#endif
#if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT)
br_x509_minimal_set_hash(&mc, br_sha1_ID, &br_sha1_vtable);
#endif
br_x509_minimal_set_hash(&mc, br_sha256_ID, &br_sha256_vtable);
#ifdef VE_SHA384_SUPPORT
br_x509_minimal_set_hash(&mc, br_sha384_ID, &br_sha384_vtable);
#endif
#ifdef VE_SHA512_SUPPORT
br_x509_minimal_set_hash(&mc, br_sha512_ID, &br_sha512_vtable);
#endif
br_x509_minimal_set_name_elements(&mc, elts, num_elts);
#ifdef HAVE_BR_X509_TIME_CHECK
br_x509_minimal_set_time_callback(&mc, NULL, verify_time_cb);
#else
#if defined(_STANDALONE) || defined(UNIT_TEST)
mc.days = (ve_utc / SECONDS_PER_DAY) + X509_DAYS_TO_UTC0;
mc.seconds = (ve_utc % SECONDS_PER_DAY);
#endif
#endif
mc.vtable->start_chain(&mc.vtable, NULL);
for (u = 0; u < VEC_LEN(chain); u ++) {
xc = &VEC_ELT(chain, u);
mc.vtable->start_cert(&mc.vtable, xc->data_len);
mc.vtable->append(&mc.vtable, xc->data, xc->data_len);
mc.vtable->end_cert(&mc.vtable);
switch (mc.err) {
case 0:
case BR_ERR_X509_OK:
case BR_ERR_X509_EXPIRED:
break;
default:
printf("u=%zu mc.err=%d\n", u, mc.err);
break;
}
}
err = mc.vtable->end_chain(&mc.vtable);
pk = NULL;
if (err) {
char date[12];
switch (err) {
case 54:
ve_error_set("Validation failed, certificate not valid as of %s",
gdate(date, sizeof(date), ve_utc));
break;
default: {
const char *err_desc = NULL;
const char *err_name = find_error_name(err, &err_desc);
if (err_name == NULL)
ve_error_set("Validation failed, err = %d",
err);
else
ve_error_set("Validation failed, %s (%s)",
err_desc, err_name);
break; }
}
} else {
tpk = mc.vtable->get_pkey(&mc.vtable, &usages);
if (tpk != NULL) {
pk = xpkeydup(tpk);
}
}
VEC_CLEAR(chain);
return (pk);
}
static int
check_forbidden_digests(br_x509_certificate *xcs, size_t num)
{
unsigned char sha256_digest[br_sha256_SIZE];
unsigned char sha384_digest[br_sha384_SIZE];
unsigned char sha512_digest[br_sha512_SIZE];
void *tbs;
hash_data *digest;
br_hash_compat_context ctx;
const br_hash_class *md;
size_t tbs_len, i;
int have_sha256, have_sha384, have_sha512;
if (VEC_LEN(forbidden_digests) == 0)
return (0);
while (num--) {
tbs = X509_to_tbs(xcs[num].data, &tbs_len);
if (tbs == NULL) {
printf("Failed to obtain TBS part of certificate\n");
return (1);
}
have_sha256 = have_sha384 = have_sha512 = 0;
for (i = 0; i < VEC_LEN(forbidden_digests); i++) {
digest = &VEC_ELT(forbidden_digests, i);
switch (digest->hash_size) {
case br_sha256_SIZE:
if (!have_sha256) {
have_sha256 = 1;
md = &br_sha256_vtable;
md->init(&ctx.vtable);
md->update(&ctx.vtable, tbs, tbs_len);
md->out(&ctx.vtable, sha256_digest);
}
if (!memcmp(sha256_digest,
digest->data,
br_sha256_SIZE))
return (1);
break;
case br_sha384_SIZE:
if (!have_sha384) {
have_sha384 = 1;
md = &br_sha384_vtable;
md->init(&ctx.vtable);
md->update(&ctx.vtable, tbs, tbs_len);
md->out(&ctx.vtable, sha384_digest);
}
if (!memcmp(sha384_digest,
digest->data,
br_sha384_SIZE))
return (1);
break;
case br_sha512_SIZE:
if (!have_sha512) {
have_sha512 = 1;
md = &br_sha512_vtable;
md->init(&ctx.vtable);
md->update(&ctx.vtable, tbs, tbs_len);
md->out(&ctx.vtable, sha512_digest);
}
if (!memcmp(sha512_digest,
digest->data,
br_sha512_SIZE))
return (1);
break;
}
}
}
return (0);
}
static br_x509_pkey *
verify_signer(const char *certs,
br_name_element *elts, size_t num_elts)
{
br_x509_certificate *xcs;
br_x509_pkey *pk;
size_t num;
pk = NULL;
ve_trust_init();
xcs = read_certificates(certs, &num);
if (xcs == NULL) {
ve_error_set("cannot read certificates\n");
return (NULL);
}
if (VEC_LEN(forbidden_anchors) > 0)
pk = verify_signer_xcs(xcs, num, elts, num_elts, &forbidden_anchors);
if (pk != NULL) {
ve_error_set("Certificate is on forbidden list\n");
xfreepkey(pk);
pk = NULL;
goto out;
}
pk = verify_signer_xcs(xcs, num, elts, num_elts, &trust_anchors);
if (pk == NULL)
goto out;
if (check_forbidden_digests(xcs, num)) {
ve_error_set("Certificate hash is on forbidden list\n");
xfreepkey(pk);
pk = NULL;
}
out:
free_certificates(xcs, num);
return (pk);
}
char *
hexdigest(char *buf, size_t bufsz, unsigned char *foo, size_t foo_len)
{
char const hex2ascii[] = "0123456789abcdef";
size_t i;
if (bufsz < (2 * foo_len) + 2)
return (NULL);
for (i = 0; i < foo_len; i++) {
buf[i * 2] = hex2ascii[foo[i] >> 4];
buf[i * 2 + 1] = hex2ascii[foo[i] & 0x0f];
}
buf[i * 2] = 0x0A;
buf[i * 2 + 1] = '\0';
return (buf);
}
#ifdef VE_ECDSA_SUPPORT
static unsigned char *
verify_ec(br_x509_pkey *pk, const char *file, const char *sigfile)
{
#ifdef VE_ECDSA_HASH_AGAIN
char *hex, hexbuf[br_sha512_SIZE * 2 + 2];
#endif
unsigned char rhbuf[br_sha512_SIZE];
br_sha256_context ctx;
unsigned char *fcp, *scp;
size_t flen, slen, plen;
pem_object *po;
const br_ec_impl *ec;
br_ecdsa_vrfy vrfy;
if ((fcp = read_file(file, &flen)) == NULL)
return (NULL);
if ((scp = read_file(sigfile, &slen)) == NULL) {
free(fcp);
return (NULL);
}
if ((po = decode_pem(scp, slen, &plen)) == NULL) {
free(fcp);
free(scp);
return (NULL);
}
br_sha256_init(&ctx);
br_sha256_update(&ctx, fcp, flen);
br_sha256_out(&ctx, rhbuf);
#ifdef VE_ECDSA_HASH_AGAIN
hex = hexdigest(hexbuf, sizeof(hexbuf), rhbuf, br_sha256_SIZE);
if (hex) {
br_sha256_init(&ctx);
br_sha256_update(&ctx, hex, strlen(hex));
br_sha256_out(&ctx, rhbuf);
}
#endif
ec = br_ec_get_default();
vrfy = br_ecdsa_vrfy_asn1_get_default();
if (!vrfy(ec, rhbuf, br_sha256_SIZE, &pk->key.ec, po->data,
po->data_len)) {
free(fcp);
fcp = NULL;
}
free(scp);
return (fcp);
}
#endif
#if defined(VE_RSA_SUPPORT) || defined(VE_OPENPGP_SUPPORT)
int
verify_rsa_digest (br_rsa_public_key *pkey,
const unsigned char *hash_oid,
unsigned char *mdata, size_t mlen,
unsigned char *sdata, size_t slen)
{
br_rsa_pkcs1_vrfy vrfy;
unsigned char vhbuf[br_sha512_SIZE];
vrfy = br_rsa_pkcs1_vrfy_get_default();
if (!vrfy(sdata, slen, hash_oid, mlen, pkey, vhbuf) ||
memcmp(vhbuf, mdata, mlen) != 0) {
return (0);
}
return (1);
}
#endif
#ifdef VE_RSA_SUPPORT
static unsigned char *
verify_rsa(br_x509_pkey *pk, const char *file, const char *sigfile)
{
unsigned char rhbuf[br_sha512_SIZE];
const unsigned char *hash_oid;
const br_hash_class *md;
br_hash_compat_context mctx;
unsigned char *fcp, *scp;
size_t flen, slen, plen, hlen;
pem_object *po;
if ((fcp = read_file(file, &flen)) == NULL)
return (NULL);
if ((scp = read_file(sigfile, &slen)) == NULL) {
free(fcp);
return (NULL);
}
if ((po = decode_pem(scp, slen, &plen)) == NULL) {
free(fcp);
free(scp);
return (NULL);
}
switch (po->data_len) {
#if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT)
case 256:
md = &br_sha1_vtable;
hlen = br_sha1_SIZE;
hash_oid = BR_HASH_OID_SHA1;
break;
#endif
default:
md = &br_sha256_vtable;
hlen = br_sha256_SIZE;
hash_oid = BR_HASH_OID_SHA256;
break;
}
md->init(&mctx.vtable);
md->update(&mctx.vtable, fcp, flen);
md->out(&mctx.vtable, rhbuf);
if (!verify_rsa_digest(&pk->key.rsa, hash_oid,
rhbuf, hlen, po->data, po->data_len)) {
free(fcp);
fcp = NULL;
}
free(scp);
return (fcp);
}
#endif
unsigned char *
verify_sig(const char *sigfile, int flags)
{
br_x509_pkey *pk;
br_name_element cn;
char cn_buf[80];
unsigned char cn_oid[4];
char pbuf[MAXPATHLEN];
char *cp;
unsigned char *ucp;
size_t n;
DEBUG_PRINTF(5, ("verify_sig: %s\n", sigfile));
n = strlcpy(pbuf, sigfile, sizeof(pbuf));
if (n > (sizeof(pbuf) - 5) || strcmp(&sigfile[n - 3], "sig") != 0)
return (NULL);
cp = strcpy(&pbuf[n - 3], "certs");
cn_oid[0] = 3;
cn_oid[1] = 0x55;
cn_oid[2] = 4;
cn_oid[3] = 3;
cn.oid = cn_oid;
cn.buf = cn_buf;
cn.len = sizeof(cn_buf);
pk = verify_signer(pbuf, &cn, 1);
if (!pk) {
printf("cannot verify: %s: %s\n", pbuf, ve_error_get());
return (NULL);
}
for (; cp > pbuf; cp--) {
if (*cp == '.') {
*cp = '\0';
break;
}
}
switch (pk->key_type) {
#ifdef VE_ECDSA_SUPPORT
case BR_KEYTYPE_EC:
ucp = verify_ec(pk, pbuf, sigfile);
break;
#endif
#ifdef VE_RSA_SUPPORT
case BR_KEYTYPE_RSA:
ucp = verify_rsa(pk, pbuf, sigfile);
break;
#endif
default:
ucp = NULL;
}
xfreepkey(pk);
if (!ucp) {
printf("Unverified %s (%s)\n", pbuf,
cn.status ? cn_buf : "unknown");
} else if ((flags & VEF_VERBOSE) != 0) {
printf("Verified %s signed by %s\n", pbuf,
cn.status ? cn_buf : "someone we trust");
}
return (ucp);
}
int
ve_check_hash(br_hash_compat_context *ctx, const br_hash_class *md,
const char *path, const char *want, size_t hlen)
{
char hexbuf[br_sha512_SIZE * 2 + 2];
unsigned char hbuf[br_sha512_SIZE];
char *hex;
int rc;
int n;
md->out(&ctx->vtable, hbuf);
#ifdef VE_PCR_SUPPORT
ve_pcr_update(path, hbuf, hlen);
#endif
hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen);
if (!hex)
return (VE_FINGERPRINT_WRONG);
n = 2*hlen;
if ((rc = strncmp(hex, want, n))) {
ve_error_set("%s: %.*s != %.*s", path, n, hex, n, want);
rc = VE_FINGERPRINT_WRONG;
}
return (rc ? rc : VE_FINGERPRINT_OK);
}
#ifdef VE_HASH_KAT_STR
static int
test_hash(const br_hash_class *md, size_t hlen,
const char *hname, const char *s, size_t slen, const char *want)
{
br_hash_compat_context mctx;
md->init(&mctx.vtable);
md->update(&mctx.vtable, s, slen);
return (ve_check_hash(&mctx, md, hname, want, hlen) != VE_FINGERPRINT_OK);
}
#endif
#define ve_test_hash(n, N) \
printf("Testing hash: " #n "\t\t\t\t%s\n", \
test_hash(&br_ ## n ## _vtable, br_ ## n ## _SIZE, #n, \
VE_HASH_KAT_STR, VE_HASH_KAT_STRLEN(VE_HASH_KAT_STR), \
vh_ ## N) ? "Failed" : "Passed")
int
ve_self_tests(void)
{
static int once = -1;
#ifdef VERIFY_CERTS_STR
br_x509_certificate *xcs;
br_x509_pkey *pk;
br_name_element cn;
char cn_buf[80];
unsigned char cn_oid[4];
size_t num;
size_t u;
#endif
if (once >= 0)
return (once);
once = 0;
DEBUG_PRINTF(5, ("Self tests...\n"));
#ifdef VE_HASH_KAT_STR
#ifdef VE_SHA1_SUPPORT
ve_test_hash(sha1, SHA1);
#endif
#ifdef VE_SHA256_SUPPORT
ve_test_hash(sha256, SHA256);
#endif
#ifdef VE_SHA384_SUPPORT
ve_test_hash(sha384, SHA384);
#endif
#ifdef VE_SHA512_SUPPORT
ve_test_hash(sha512, SHA512);
#endif
#endif
#ifdef VERIFY_CERTS_STR
xcs = parse_certificates(__DECONST(unsigned char *, VERIFY_CERTS_STR),
sizeof(VERIFY_CERTS_STR), &num);
if (xcs != NULL) {
cn_oid[0] = 3;
cn_oid[1] = 0x55;
cn_oid[2] = 4;
cn_oid[3] = 3;
cn.oid = cn_oid;
cn.buf = cn_buf;
for (u = 0; u < num; u ++) {
cn.len = sizeof(cn_buf);
if ((pk = verify_signer_xcs(&xcs[u], 1, &cn, 1, &trust_anchors)) != NULL) {
free_cert_contents(&xcs[u]);
once++;
printf("Testing verify certificate: %s\tPassed\n",
cn.status ? cn_buf : "");
xfreepkey(pk);
}
}
if (!once)
printf("Testing verify certificate:\t\t\tFailed\n");
xfree(xcs);
}
#endif
#ifdef VE_OPENPGP_SUPPORT
if (!openpgp_self_tests())
once++;
#endif
return (once);
}