diff options
Diffstat (limited to 'lib/libsecureboot')
-rw-r--r-- | lib/libsecureboot/Makefile | 1 | ||||
-rw-r--r-- | lib/libsecureboot/Makefile.inc | 13 | ||||
-rw-r--r-- | lib/libsecureboot/Makefile.libsa.inc | 8 | ||||
-rw-r--r-- | lib/libsecureboot/README.rst | 17 | ||||
-rw-r--r-- | lib/libsecureboot/h/libsecureboot.h | 1 | ||||
-rw-r--r-- | lib/libsecureboot/h/verify_file.h | 1 | ||||
-rw-r--r-- | lib/libsecureboot/local.trust.mk | 145 | ||||
-rw-r--r-- | lib/libsecureboot/openpgp/Makefile.inc | 1 | ||||
-rw-r--r-- | lib/libsecureboot/openpgp/opgp_sig.c | 13 | ||||
-rw-r--r-- | lib/libsecureboot/tests/Makefile | 1 | ||||
-rw-r--r-- | lib/libsecureboot/vectx.c | 26 | ||||
-rw-r--r-- | lib/libsecureboot/verify_file.c | 37 | ||||
-rw-r--r-- | lib/libsecureboot/vets.c | 44 |
13 files changed, 178 insertions, 130 deletions
diff --git a/lib/libsecureboot/Makefile b/lib/libsecureboot/Makefile index 3ae4d5e69a52..85167e57abf2 100644 --- a/lib/libsecureboot/Makefile +++ b/lib/libsecureboot/Makefile @@ -1,4 +1,3 @@ - .include <src.opts.mk> LIB= secureboot diff --git a/lib/libsecureboot/Makefile.inc b/lib/libsecureboot/Makefile.inc index ff40b919bad3..21ad019a0cb5 100644 --- a/lib/libsecureboot/Makefile.inc +++ b/lib/libsecureboot/Makefile.inc @@ -1,4 +1,3 @@ - .if empty(BEARSSL) .include "../libbearssl/Makefile.inc" .endif @@ -58,6 +57,10 @@ _2ndLAST_PEM_USE: .USE sed -n "`grep -n .-BEGIN ${.ALLSRC:M*.pem} | tail -2 | \ sed 's,:.*,,' | xargs | (read a b; echo $$a,$$(($$b - 1)))`p" ${.ALLSRC:M*.pem} > ${.TARGET} +# rules to populate the [tv]*.pem files we use to generate ta.h +# and can add/alter VE_*_LIST as desired. +.-include "local.trust.mk" + # list of hashes we support VE_HASH_LIST?= SHA256 @@ -74,16 +77,16 @@ VE_SIGNATURE_EXT_LIST?= sig # needs to be yes for FIPS 140-2 compliance VE_SELF_TESTS?= no -# rules to populate the [tv]*.pem files we use to generate ta.h -# and can add/alter VE_*_LIST as desired. -.-include "local.trust.mk" +CFLAGS+= -I. +.if ${VE_SIGNATURE_EXT_LIST:M*sig} != "" # this is what we use as our trust anchor -CFLAGS+= -I. -DTRUST_ANCHOR_STR=ta_PEM +CFLAGS+= -DTRUST_ANCHOR_STR=ta_PEM .if ${VE_SELF_TESTS} != "no" XCFLAGS.vets+= -DVERIFY_CERTS_STR=vc_PEM .endif +.endif # clean these up VE_HASH_LIST:= ${VE_HASH_LIST:tu:O:u} diff --git a/lib/libsecureboot/Makefile.libsa.inc b/lib/libsecureboot/Makefile.libsa.inc index 76e0a91bc20a..7397d0fc1144 100644 --- a/lib/libsecureboot/Makefile.libsa.inc +++ b/lib/libsecureboot/Makefile.libsa.inc @@ -1,4 +1,3 @@ - BRSSL_CFLAGS+= -DNO_STDIO .include "Makefile.inc" @@ -46,9 +45,12 @@ manifests.h: echo '${VE_MANIFEST_LIST:@m@"$m",${.newline}@}'; \ echo 'NULL };' ) > ${.TARGET} +# only add these if set XCFLAGS.verify_file+= \ - -DVE_DEBUG_LEVEL=${VE_DEBUG_LEVEL:U0} \ - -DVE_VERBOSE_DEFAULT=${VE_VERBOSE_DEFAULT:U0} \ + ${VE_DEBUG_LEVEL \ + VE_VERBOSE_DEFAULT \ + VE_VERIFY_FLAGS \ + :L:@v@${$v:S,^,-D$v=,}@} .if !empty(MANIFEST_SKIP_ALWAYS) XCFLAGS.verify_file+= -DMANIFEST_SKIP_ALWAYS=\"${MANIFEST_SKIP_ALWAYS}\" diff --git a/lib/libsecureboot/README.rst b/lib/libsecureboot/README.rst index 85b949db58cc..f1d3c5679d35 100644 --- a/lib/libsecureboot/README.rst +++ b/lib/libsecureboot/README.rst @@ -1,7 +1,8 @@ libsecureboot ************* -This library depends one way or another on verifying digital signatures. +This library depends one way or another on verifying detached digital +signatures. To do that, the necessary trust anchors need to be available. The simplest (and most attractive for an embedded system) is to @@ -16,7 +17,7 @@ provide access to the necessary trust anchors. That signing server is freely available - see http://www.crufty.net/sjg/docs/signing-server.htm -X.509 certificates chains offer a lot of flexibility over time and are +X.509 certificate chains offer a lot of flexibility over time and are a great solution for an embedded vendor like Juniper or even FreeBSD.org, but are probably overkill for personal or small site use. @@ -74,8 +75,12 @@ header. Signatures ---------- -We expect ascii armored (``.asc``) detached signatures. -Eg. signature for ``manifest`` would be in ``manifest.asc`` +We expect ascii armored (``.asc``) detached signatures +Eg.:: + + gpg -a --detach-sign manifest + +should produce the expected signature in ``manifest.asc`` We only support version 4 signatures using RSA (the default for ``gpg``). @@ -108,6 +113,10 @@ Ie. client sends a hash which during signing gets hashed again. So for Junos we define VE_ECDSA_HASH_AGAIN which causes ``verify_ec`` to hash again. +Later I added a FakeHash class to the signing server so we could +generate signatures compatible with our previous RSA scheme and +others. + Otherwise our EC DSA and RSA signatures are the default used by OpenSSL - an original design goal was that a customer could verify our signatures using nothing but an ``openssl`` binary. diff --git a/lib/libsecureboot/h/libsecureboot.h b/lib/libsecureboot/h/libsecureboot.h index 017558536825..d32df9594332 100644 --- a/lib/libsecureboot/h/libsecureboot.h +++ b/lib/libsecureboot/h/libsecureboot.h @@ -29,6 +29,7 @@ #include <sys/param.h> #ifdef _STANDALONE +#define _DEBUG_LEVEL_VAR DebugVe #include <stand.h> #else #include <sys/types.h> diff --git a/lib/libsecureboot/h/verify_file.h b/lib/libsecureboot/h/verify_file.h index 88d758b27af4..f918ed6d0e38 100644 --- a/lib/libsecureboot/h/verify_file.h +++ b/lib/libsecureboot/h/verify_file.h @@ -46,6 +46,7 @@ int verify_prep(int, const char *, off_t, struct stat *, const char *); void ve_debug_set(int); char *ve_error_get(void); void ve_efi_init(void); +void ve_status_set(int, int); int ve_status_get(int); int load_manifest(const char *, const char *, const char *, struct stat *); int pass_manifest(const char *, const char *); diff --git a/lib/libsecureboot/local.trust.mk b/lib/libsecureboot/local.trust.mk index 7b1e5f7ee97b..f2da3d3ac452 100644 --- a/lib/libsecureboot/local.trust.mk +++ b/lib/libsecureboot/local.trust.mk @@ -5,65 +5,69 @@ # the signing server (http://www.crufty.net/sjg/blog/signing-server.htm) # for each key will provide the appropriate certificate chain on request -# force these for Junos -#MANIFEST_SKIP_ALWAYS= boot -VE_HASH_LIST= \ - SHA1 \ - SHA256 \ - SHA384 \ - SHA512 - -VE_SIGNATURE_LIST= \ - ECDSA \ - RSA - -VE_SIGNATURE_EXT_LIST= \ - esig \ - rsig - -VE_SELF_TESTS= yes - -.if ${MACHINE} == "host" && ${.CURDIR:T} == "tests" - -VE_SIGNATURE_LIST+= \ - DEPRECATED_RSA_SHA1 +# allow site control +.-include "site.trust.mk" -VE_SIGNATURE_EXT_LIST+= \ - sig -.endif +#VE_DEBUG_LEVEL?=3 +#VE_VERBOSE_DEFAULT?=2 -# add OpenPGP support - possibly dormant -VE_SIGNATURE_LIST+= OPENPGP -VE_SIGNATURE_EXT_LIST+= asc +VE_HASH_LIST?= \ + SHA256 \ + SHA384 \ -# allow site override of all the above -.-include "site.trust.mk" +VE_SELF_TESTS?= yes -SIGNER ?= ${SB_TOOLS_PATH:U/volume/buildtools/bin}/sign.py +# client for the signing server above +SIGNER?= /opt/sigs/sign.py .if exists(${SIGNER}) -SIGN_HOST ?= ${SB_SITE:Usvl}-junos-signer.juniper.net -ECDSA_PORT:= ${133%y:L:gmtime} -SIGN_ECDSA= ${PYTHON} ${SIGNER} -u ${SIGN_HOST}:${ECDSA_PORT} -h sha256 -RSA2_PORT:= ${163%y:L:gmtime} -SIGN_RSA2= ${PYTHON} ${SIGNER} -u ${SIGN_HOST}:${RSA2_PORT} -h sha256 +OPENPGP_SIGNER?= ${SIGNER:H}/openpgp-sign.py +OPENPGP_SIGN_FLAGS= -a +OPENPGP_SIGN_HOST?= localhost +SIGN_HOST ?= localhost + +# A list of name/ext/url tuples. +# name should be one of ECDSA, OPENPGP or RSA, they can be repeated +# Order of ext list implies runtime preference so do not sort! +VE_SIGN_URL_LIST?= \ + ECDSA/esig/${SIGN_HOST}:${133%y:L:localtime} \ + RSA/rsig/${SIGN_HOST}:${163%y:L:localtime} \ + OPENPGP/asc/${OPENPGP_SIGN_HOST}:1234 \ + +.for sig ext url in ${VE_SIGN_URL_LIST:@x@${x:H:H} ${x:H:T} ${x:T}@} +SIGN_${sig}:= ${PYTHON} ${${sig}_SIGNER:U${SIGNER}} -u ${url} ${${sig}_SIGN_FLAGS:U-h sha256} + +VE_SIGNATURE_LIST+= ${sig} +VE_SIGNATURE_EXT_LIST+= ${ext} + +_SIGN_${sig}_USE: .USE + ${SIGN_${sig}} ${.ALLSRC} + +_TA_${sig}_USE: .USE + ${SIGN_${sig}} -C ${.TARGET} + +.if ${sig} == "OPENPGP" +ta_${sig:tl}.${ext}: _TA_${sig}_USE +ta_${ext}.h: ta_${sig:tl}.${ext} +.else +${ext:S/sig/certs/}.pem: _TA_${sig}_USE +# the last cert in the chain is the one we want +ta_${ext}.pem: ${ext:S/sig/certs/}.pem _LAST_PEM_USE +ta.h: ta_${ext}.pem +.if ${VE_SELF_TESTS} != "no" +# we use the 2nd last cert to test verification +vc_${ext}.pem: ${ext:S/sig/certs/}.pem _2ndLAST_PEM_USE +ta.h: vc_${ext}.pem +.endif +.endif +.endfor -# deal with quirk of our .esig format -XCFLAGS.vets+= -DVE_ECDSA_HASH_AGAIN +# cleanup duplicates +VE_SIGNATURE_LIST:= ${VE_SIGNATURE_LIST:O:u} -.if !empty(OPENPGP_SIGN_URL) +.if target(ta_asc.h) XCFLAGS.opgp_key+= -DHAVE_TA_ASC_H -VE_SIGNATURE_LIST+= OPENPGP -VE_SIGNATURE_EXT_LIST+= asc - -SIGN_OPENPGP= ${PYTHON} ${SIGNER:H}/openpgp-sign.py -a -u ${OPENPGP_SIGN_URL} - -ta_openpgp.asc: - ${SIGN_OPENPGP} -C ${.TARGET} - -ta_asc.h: ta_openpgp.asc - .if ${VE_SELF_TESTS} != "no" # for self test vc_openpgp.asc: ta_openpgp.asc @@ -74,48 +78,26 @@ ta_asc.h: vc_openpgp.asc .endif .endif -rcerts.pem: - ${SIGN_RSA2} -C ${.TARGET} - -ecerts.pem: - ${SIGN_ECDSA} -C ${.TARGET} - -.if ${VE_SIGNATURE_LIST:tu:MECDSA} != "" -# the last cert in the chain is the one we want -ta_ec.pem: ecerts.pem _LAST_PEM_USE -ta.h: ta_ec.pem -.if ${VE_SELF_TESTS} != "no" -# these are for verification self test -vc_ec.pem: ecerts.pem _2ndLAST_PEM_USE -ta.h: vc_ec.pem -.endif -.endif - -.if ${VE_SIGNATURE_LIST:tu:MRSA} != "" -ta_rsa.pem: rcerts.pem _LAST_PEM_USE -ta.h: ta_rsa.pem -.if ${VE_SELF_TESTS} != "no" -vc_rsa.pem: rcerts.pem _2ndLAST_PEM_USE -ta.h: vc_rsa.pem -.endif -.endif - -# we take the mtime of this as our baseline time -#BUILD_UTC_FILE= ecerts.pem -#VE_DEBUG_LEVEL=3 -#VE_VERBOSE_DEFAULT=1 - .else +VE_SIGNATURE_LIST?= RSA + # you need to provide t*.pem or t*.asc files for each trust anchor +# below assumes they are named ta_${ext}.pem eg ta_esig.pem for ECDSA .if empty(TRUST_ANCHORS) -TRUST_ANCHORS!= cd ${.CURDIR} && 'ls' -1 *.pem t*.asc 2> /dev/null +TRUST_ANCHORS!= cd ${.CURDIR} && 'ls' -1 *.pem t*.asc 2> /dev/null || echo .endif .if empty(TRUST_ANCHORS) && ${MK_LOADER_EFI_SECUREBOOT} != "yes" .error Need TRUST_ANCHORS see ${.PARSEDIR}/README.rst .endif + .if ${TRUST_ANCHORS:T:Mt*.pem} != "" ta.h: ${TRUST_ANCHORS:M*.pem} +VE_SIGNATURE_EXT_LIST?= ${TRUST_ANCHORS:T:Mt*.pem:R:S/ta_//} +.if ${VE_SIGNATURE_EXT_LIST:Mesig} != "" +VE_SIGNATURE_LIST+= ECDSA +.endif .endif + .if ${TRUST_ANCHORS:T:Mt*.asc} != "" VE_SIGNATURE_LIST+= OPENPGP VE_SIGNATURE_EXT_LIST+= asc @@ -124,4 +106,3 @@ ta_asc.h: ${TRUST_ANCHORS:M*.asc} # we take the mtime of this as our baseline time BUILD_UTC_FILE?= ${TRUST_ANCHORS:[1]} .endif - diff --git a/lib/libsecureboot/openpgp/Makefile.inc b/lib/libsecureboot/openpgp/Makefile.inc index 0d9a01a80369..3a216d205fe3 100644 --- a/lib/libsecureboot/openpgp/Makefile.inc +++ b/lib/libsecureboot/openpgp/Makefile.inc @@ -1,4 +1,3 @@ - # decode OpenPGP signatures per rfc4880 .PATH: ${.PARSEDIR} diff --git a/lib/libsecureboot/openpgp/opgp_sig.c b/lib/libsecureboot/openpgp/opgp_sig.c index a6aa787ee5c0..8846296d7122 100644 --- a/lib/libsecureboot/openpgp/opgp_sig.c +++ b/lib/libsecureboot/openpgp/opgp_sig.c @@ -26,8 +26,6 @@ * RCSid: * from: signer.c,v 1.10 2018/03/23 01:14:30 sjg * - * @(#) Copyright (c) 2012 Simon J. Gerraty - * * This file is provided in the hope that it will * be of use. There is absolutely NO WARRANTY. * Permission to copy, redistribute or otherwise @@ -341,8 +339,19 @@ openpgp_verify(const char *filename, mlen = br_sha256_SIZE; hash_oid = BR_HASH_OID_SHA256; break; + case 9: /* sha384 */ + md = &br_sha384_vtable; + mlen = br_sha384_SIZE; + hash_oid = BR_HASH_OID_SHA384; + break; + case 10: /* sha512 */ + md = &br_sha512_vtable; + mlen = br_sha512_SIZE; + hash_oid = BR_HASH_OID_SHA512; + break; default: warnx("unsupported hash algorithm: %s", hname); + rc = -1; goto oops; } md->init(&mctx.vtable); diff --git a/lib/libsecureboot/tests/Makefile b/lib/libsecureboot/tests/Makefile index 70e10bb4f984..b3de2b6ce5b9 100644 --- a/lib/libsecureboot/tests/Makefile +++ b/lib/libsecureboot/tests/Makefile @@ -1,4 +1,3 @@ - .include <src.opts.mk> PROG= tvo diff --git a/lib/libsecureboot/vectx.c b/lib/libsecureboot/vectx.c index dba728421ce4..2d56830cd81d 100644 --- a/lib/libsecureboot/vectx.c +++ b/lib/libsecureboot/vectx.c @@ -306,19 +306,31 @@ vectx_lseek(struct vectx *ctx, off_t off, int whence) DEBUG_PRINTF(3, ("%s(%s, %ld, %d)\n", __func__, ctx->vec_path, (long)off, whence)); if (whence == SEEK_END && off <= 0) { - if (ctx->vec_closing && ctx->vec_hashed < ctx->vec_size) { - DEBUG_PRINTF(3, ("%s: SEEK_END %ld\n", - __func__, - (long)(ctx->vec_size - ctx->vec_hashed))); + if (ctx->vec_size < 0) { + if (ctx->vec_closing) { + /* size unknown - read until EOF */ + do { + n = vectx_read(ctx, buf, PAGE_SIZE); + if (n < 0) + return (n); + } while (n > 0); + return (ctx->vec_off); + } + } else { + if (ctx->vec_closing && ctx->vec_hashed < ctx->vec_size) { + DEBUG_PRINTF(3, ("%s: SEEK_END %ld\n", + __func__, + (long)(ctx->vec_size - ctx->vec_hashed))); + } + whence = SEEK_SET; + off += ctx->vec_size; } - whence = SEEK_SET; - off += ctx->vec_size; } else if (whence == SEEK_CUR) { whence = SEEK_SET; off += ctx->vec_off; } if (whence != SEEK_SET || - off > ctx->vec_size) { + (off > ctx->vec_size && ctx->vec_size > 0)) { printf("ERROR: %s: unsupported operation: whence=%d off=%ld -> %ld\n", __func__, whence, (long)ctx->vec_off, (long)off); return (-1); diff --git a/lib/libsecureboot/verify_file.c b/lib/libsecureboot/verify_file.c index 1e1c714d1fa8..753204a33b6a 100644 --- a/lib/libsecureboot/verify_file.c +++ b/lib/libsecureboot/verify_file.c @@ -25,7 +25,7 @@ /* * Routines to verify files loaded. */ -#include <sys/cdefs.h> + #include <sys/param.h> #include <string.h> #include <sys/queue.h> @@ -82,7 +82,7 @@ static int Verbose = VE_VERBOSE_DEFAULT; /** * @brief set ve status for fd */ -static void +void ve_status_set(int fd, int ves) { if (fd >= 0 && fd < SOPEN_MAX) { @@ -131,15 +131,21 @@ int is_verified(struct stat *stp) { struct verify_status *vsp; + int rc = VE_NOT_CHECKED; if (stp->st_ino > 0) { for (vsp = verified_files; vsp != NULL; vsp = vsp->vs_next) { if (stp->st_dev == vsp->vs_dev && - stp->st_ino == vsp->vs_ino) - return (vsp->vs_status); + stp->st_ino == vsp->vs_ino) { + rc = vsp->vs_status; + break; + } } } - return (VE_NOT_CHECKED); + DEBUG_PRINTF(4, ("%s: dev=%lld,ino=%llu,status=%d\n", + __func__, (long long)stp->st_dev, + (unsigned long long)stp->st_ino, rc)); + return (rc); } /* most recent first, since most likely to see repeated calls. */ @@ -156,6 +162,9 @@ add_verify_status(struct stat *stp, int status) vsp->vs_status = status; verified_files = vsp; } + DEBUG_PRINTF(4, ("%s: dev=%lld,ino=%llu,status=%d\n", + __func__, (long long)stp->st_dev, + (unsigned long long)stp->st_ino, status)); } @@ -270,11 +279,14 @@ severity_guess(const char *filename) /* * Some files like *.conf and *.hints may be unsigned, * a *.tgz is expected to have its own signed manifest. + * We allow *.conf to get VE_WANT, but files we expect + * to always be unverified get VE_TRY and we will not + * report them. */ if ((cp = strrchr(filename, '.'))) { - if (strcmp(cp, ".conf") == 0 || - strcmp(cp, ".cookie") == 0 || + if (strcmp(cp, ".cookie") == 0 || strcmp(cp, ".hints") == 0 || + strcmp(cp, ".order") == 0 || strcmp(cp, ".tgz") == 0) return (VE_TRY); if (strcmp(cp, ".4th") == 0 || @@ -398,6 +410,8 @@ void verify_report(const char *path, int severity, int status, struct stat *stp) { if (status < 0 || status == VE_FINGERPRINT_IGNORE) { + if (Verbose < VE_VERBOSE_ALL && severity < VE_WANT) + return; if (Verbose >= VE_VERBOSE_UNVERIFIED || severity > VE_TRY || status <= VE_FINGERPRINT_WRONG) { if (Verbose == VE_VERBOSE_DEBUG && stp != NULL) @@ -462,9 +476,10 @@ verify_prep(int fd, const char *filename, off_t off, struct stat *stp, caller, fd, filename, (long long)off, (long long)stp->st_dev, (unsigned long long)stp->st_ino)); rc = is_verified(stp); - DEBUG_PRINTF(4,("verify_prep: is_verified()->%d\n", rc)); if (rc == VE_NOT_CHECKED) { rc = find_manifest(filename); + if (rc == VE_VERIFIED) + rc = VE_NOT_CHECKED; } else { ve_status_set(fd, rc); } @@ -511,7 +526,8 @@ verify_file(int fd, const char *filename, off_t off, int severity, if (check_verbose) { check_verbose = 0; Verbose = getenv_int("VE_VERBOSE", VE_VERBOSE_DEFAULT); - VerifyFlags = getenv_int("VE_VERIFY_FLAGS", VEF_VERBOSE); + VerifyFlags = getenv_int("VE_VERIFY_FLAGS", + Verbose ? VEF_VERBOSE : 0); #ifndef UNIT_TEST ve_debug_set(getenv_int("VE_DEBUG_LEVEL", VE_DEBUG_LEVEL)); #endif @@ -523,6 +539,9 @@ verify_file(int fd, const char *filename, off_t off, int severity, return (0); if (rc != VE_FINGERPRINT_WRONG && loaded_manifests) { + if (rc != VE_NOT_CHECKED) + return (rc); + if (severity <= VE_GUESS) severity = severity_guess(filename); #ifdef VE_PCR_SUPPORT diff --git a/lib/libsecureboot/vets.c b/lib/libsecureboot/vets.c index 4a2aba433191..67d27d567485 100644 --- a/lib/libsecureboot/vets.c +++ b/lib/libsecureboot/vets.c @@ -200,11 +200,13 @@ ve_utc_set(time_t utc) } } +#ifdef VERIFY_CERTS_STR static void free_cert_contents(br_x509_certificate *xc) { xfree(xc->data); } +#endif /* * a bit of a dance to get commonName from a certificate @@ -372,13 +374,15 @@ ve_trust_anchors_add_buf(unsigned char *buf, size_t len) size_t num; num = 0; - xcs = parse_certificates(buf, len, &num); - if (xcs != NULL) { - num = ve_trust_anchors_add(xcs, num); + 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); + } else { + num = openpgp_trust_add_buf(buf, len); #endif + } } return (num); } @@ -398,15 +402,17 @@ ve_trust_anchors_revoke(unsigned char *buf, size_t len) size_t num; num = 0; - xcs = parse_certificates(buf, len, &num); - if (xcs != NULL) { - num = ve_forbidden_anchors_add(xcs, num); + 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); + } else { + if (buf[len - 1] == '\n') + buf[len - 1] = '\0'; + num = openpgp_trust_revoke((char *)buf); #endif + } } return (num); } @@ -568,9 +574,17 @@ verify_signer_xcs(br_x509_certificate *xcs, ve_error_set("Validation failed, certificate not valid as of %s", gdate(date, sizeof(date), ve_utc)); break; - default: - ve_error_set("Validation failed, err = %d", err); - 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); |