Commit eb1a6a62 authored by André Guerreiro's avatar André Guerreiro Committed by Albert Astals Cid

Core: Support for digital signatures

Coded with André Esser <bepandre@hotmail.com>

Bug #16770
parent b14d4b09
......@@ -105,6 +105,7 @@ endif(WITH_FONTCONFIGURATION_FONTCONFIG)
macro_optional_find_package(JPEG)
macro_optional_find_package(PNG)
macro_optional_find_package(TIFF)
find_package(NSS3 REQUIRED)
if(JPEG_FOUND)
set(ENABLE_LIBJPEG ${JPEG_FOUND})
endif(JPEG_FOUND)
......@@ -201,6 +202,9 @@ if(ENABLE_LIBCURL)
include_directories(${CURL_INCLUDE_DIR})
set(POPPLER_HAS_CURL_SUPPORT ON)
endif(ENABLE_LIBCURL)
if (NSS3_FOUND)
add_definitions(${NSS3_CFLAGS})
endif(NSS3_FOUND)
add_definitions(-DHAVE_CONFIG_H=1)
if(MINGW)
......@@ -364,6 +368,8 @@ set(poppler_SRCS
poppler/ProfileData.cc
poppler/PreScanOutputDev.cc
poppler/PSTokenizer.cc
poppler/SignatureHandler.cc
poppler/SignatureInfo.cc
poppler/Stream.cc
poppler/StructTreeRoot.cc
poppler/StructElement.cc
......@@ -412,6 +418,9 @@ endif(ENABLE_SPLASH)
if(FONTCONFIG_FOUND)
set(poppler_LIBS ${poppler_LIBS} ${FONTCONFIG_LIBRARIES})
endif(FONTCONFIG_FOUND)
if (NSS3_FOUND)
set(poppler_LIBS ${poppler_LIBS} ${NSS3_LIBRARIES})
endif(NSS3_FOUND)
if(JPEG_FOUND)
set(poppler_SRCS ${poppler_SRCS}
poppler/DCTStream.cc
......
# - try to find NSS3 libraries
# Once done this will define
#
# NSS_FOUND - system has NSS3
# NSS3_CFLAGS - the NSS CFlags
# NSS3_LIBRARIES - Link these to use NSS
#
# Copyright 2015 André Guerreiro, <aguerreiro1985@gmail.com>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
include(FindPackageHandleStandardArgs)
if (NOT WIN32)
find_package(PkgConfig REQUIRED)
pkg_check_modules(NSS3 "nss>=3.19")
find_package_handle_standard_args(NSS3 DEFAULT_MSG NSS3_LIBRARIES NSS3_CFLAGS)
endif(NOT WIN32)
......@@ -264,6 +264,8 @@ else
enable_libopenjpeg=no
fi
PKG_CHECK_MODULES(NSS3, nss, [], [])
AM_CONDITIONAL(BUILD_LIBOPENJPEG, test x$openjpeg1 = xyes || test x$openjpeg2 = xyes)
AH_TEMPLATE([ENABLE_LIBOPENJPEG],
[Use libopenjpeg instead of builtin jpeg2000 decoder.])
......
......@@ -4,6 +4,8 @@
//
// Copyright (C) 2008 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
// Copyright (C) 2015 André Guerreiro <aguerreiro1985@gmail.com>
// Copyright (C) 2015 André Esser <bepandre@hotmail.com>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
......@@ -116,3 +118,27 @@ GooString *timeToDateString(time_t *timet) {
return dateString;
}
time_t pdfTimeToInteger(GooString *time_str)
{
int year, mon, day, hour, min, sec, tz_hour, tz_minute;
char tz;
struct tm time_struct;
if (!parseDateString (time_str->getCString(), &year,
&mon, &day, &hour, &min, &sec, &tz, &tz_hour, &tz_minute))
return 0;
time_struct.tm_year = year - 1900;
time_struct.tm_mon = mon - 1;
time_struct.tm_mday = day;
time_struct.tm_hour = hour;
time_struct.tm_min = min;
time_struct.tm_sec = sec;
time_struct.tm_wday = -1;
time_struct.tm_yday = -1;
time_struct.tm_isdst = -1;
time_t unix_time = mktime(&time_struct);
return unix_time;
}
......@@ -4,6 +4,8 @@
//
// Copyright (C) 2008 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
// Copyright (C) 2015 André Guerreiro <aguerreiro1985@gmail.com>
// Copyright (C) 2015 André Esser <bepandre@hotmail.com>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
......@@ -31,5 +33,6 @@ GBool parseDateString(const char *string, int *year, int *month, int *day, int *
* If timet is NULL, current time is used.
*/
GooString *timeToDateString(time_t *timet);
time_t pdfTimeToInteger(GooString *time_str);
#endif
......@@ -15,7 +15,9 @@
// Copyright 2009 KDAB via Guillermo Amaral <gamaral@amaral.com.mx>
// Copyright 2010, 2012 Mark Riedesel <mark@klowner.com>
// Copyright 2012 Fabio D'Urso <fabiodurso@hotmail.it>
//
// Copyright 2015 André Guerreiro <aguerreiro1985@gmail.com>
// Copyright 2015 André Esser <bepandre@hotmail.com>
//
//========================================================================
#include <config.h>
......@@ -36,6 +38,8 @@
#include "Gfx.h"
#include "Form.h"
#include "PDFDoc.h"
#include "DateInfo.h"
#include "SignatureHandler.h"
#include "XRef.h"
#include "PDFDocEncoding.h"
#include "Annot.h"
......@@ -441,6 +445,11 @@ FormWidgetSignature::FormWidgetSignature(PDFDoc *docA, Object *aobj, unsigned nu
parent = static_cast<FormFieldSignature*>(field);
}
SignatureInfo *FormWidgetSignature::validateSignature(bool doVerifyCert, bool forceRevalidation)
{
return parent->validateSignature(doVerifyCert, forceRevalidation);
}
void FormWidgetSignature::updateWidgetAppearance()
{
// Unimplemented
......@@ -1370,11 +1379,114 @@ GooString *FormFieldChoice::getSelectedChoice() {
FormFieldSignature::FormFieldSignature(PDFDoc *docA, Object *dict, const Ref& ref, FormField *parent, std::set<int> *usedParents)
: FormField(docA, dict, ref, parent, usedParents, formSignature)
{
signature = NULL;
signature_info = new SignatureInfo();
parseInfo();
}
FormFieldSignature::~FormFieldSignature()
{
if (byte_range) {
byte_range->free();
delete byte_range;
}
}
void FormFieldSignature::parseInfo()
{
if (obj.isDict()) {
Object sig_dict, contents_obj, byterange_obj, time_of_signing, subfilterName;
// retrieve PKCS#7
obj.dictLookup("V", &sig_dict);
sig_dict.dictLookup("Contents", &contents_obj);
if (contents_obj.isString()) {
GooString *str = contents_obj.getString();
signature_len = str->getLength();
signature = (unsigned char *)gmalloc(signature_len);
memcpy(signature, str->getCString(), signature_len);
}
contents_obj.free();
sig_dict.dictLookup("ByteRange", &byterange_obj);
if (byterange_obj.isArray()) {
byte_range = new Object(byterange_obj);
}
// retrieve SigningTime
sig_dict.dictLookup("M", &time_of_signing);
if (!time_of_signing.isNull()) {
GooString *time_str = time_of_signing.getString();
signature_info->setSigningTime(pdfTimeToInteger(time_str)); // Put this information directly in SignatureInfo object
time_of_signing.free();
}
// check if subfilter is supported for signature validation, only detached signatures work for now
sig_dict.dictLookup("SubFilter", &subfilterName);
if (subfilterName.isName() && strcmp(subfilterName.getName(), "adbe.pkcs7.detached") == 0) {
signature_info->setSubFilterSupport(true);
}
subfilterName.free();
sig_dict.free();
}
}
SignatureInfo *FormFieldSignature::validateSignature(bool doVerifyCert, bool forceRevalidation)
{
if (!signature_info->isSubfilterSupported()) {
error(errUnimplemented, 0, "Unable to validate this type of signature");
return signature_info;
}
if (signature_info->getSignatureValStatus() != SIGNATURE_NOT_VERIFIED && !forceRevalidation) {
return signature_info;
}
if (byte_range == NULL || !byte_range->isArray() || signature == NULL) {
return signature_info;
}
Object r2, r3, r4;
NSSCMSVerificationStatus sig_val_state;
SECErrorCodes cert_val_state;
byte_range->arrayGet(1, &r2);
byte_range->arrayGet(2, &r3);
byte_range->arrayGet(3, &r4);
unsigned int signed_data_len = r2.getInt()+r4.getInt();
unsigned char *to_check = (unsigned char *)gmalloc(signed_data_len);
//Read the 2 slices of data that are signed
doc->getBaseStream()->setPos(0);
doc->getBaseStream()->doGetChars(r2.getInt(), to_check);
doc->getBaseStream()->setPos(r3.getInt());
doc->getBaseStream()->doGetChars(r4.getInt(), to_check+r2.getInt());
SignatureHandler signature_handler(signature, signature_len);
sig_val_state = signature_handler.ValidateSignature(to_check, signed_data_len);
signature_info->setSignatureValStatus(SignatureHandler::NSS_SigTranslate(sig_val_state));
signature_info->setSignerName(signature_handler.getSignerName());
// verify if signature contains a 'signing time' attribute
if (signature_handler.getSigningTime() != 0) {
signature_info->setSigningTime(signature_handler.getSigningTime());
}
if (sig_val_state != NSSCMSVS_GoodSignature || !doVerifyCert) {
return signature_info;
}
cert_val_state = signature_handler.ValidateCertificate();
signature_info->setCertificateValStatus(SignatureHandler::NSS_CertTranslate(cert_val_state));
free(to_check);
return signature_info;
}
#ifdef DEBUG_FORMS
......@@ -1475,7 +1587,7 @@ Form::Form(PDFDoc *docA, Object* acroFormA)
Form::~Form() {
int i;
for(i = 0; i< numFields; ++i)
for(i = 0; i < numFields; ++i)
delete rootFields[i];
gfree (rootFields);
delete defaultAppearance;
......
......@@ -11,6 +11,8 @@
// Copyright 2011 Pino Toscano <pino@kde.org>
// Copyright 2012 Fabio D'Urso <fabiodurso@hotmail.it>
// Copyright 2013 Adrian Johnson <ajohnson@redneon.com>
// Copyright 2015 André Guerreiro <aguerreiro1985@gmail.com>
// Copyright 2015 André Esser <bepandre@hotmail.com>
//
//========================================================================
......@@ -35,6 +37,8 @@ class Annots;
class LinkAction;
class GfxResources;
class PDFDoc;
class SignatureInfo;
class SignatureHandler;
enum FormFieldType {
formButton,
......@@ -245,6 +249,9 @@ class FormWidgetSignature: public FormWidget {
public:
FormWidgetSignature(PDFDoc *docA, Object *dict, unsigned num, Ref ref, FormField *p);
void updateWidgetAppearance();
SignatureInfo *validateSignature(bool doVerifyCert, bool forceRevalidation);
protected:
FormFieldSignature *parent;
};
......@@ -487,8 +494,17 @@ class FormFieldSignature: public FormField {
public:
FormFieldSignature(PDFDoc *docA, Object *dict, const Ref& ref, FormField *parent, std::set<int> *usedParents);
SignatureInfo *validateSignature(bool doVerifyCert, bool forceRevalidation);
virtual ~FormFieldSignature();
private:
void parseInfo();
Object *byte_range;
unsigned char *signature;
unsigned int signature_len;
SignatureInfo *signature_info;
#ifdef DEBUG_FORMS
void print(int indent = 0);
#endif
......
......@@ -166,6 +166,8 @@ poppler_include_HEADERS = \
PreScanOutputDev.h \
PSTokenizer.h \
Rendition.h \
SignatureHandler.h \
SignatureInfo.h \
StdinCachedFile.h \
StdinPDFDocBuilder.h \
Stream-CCITT.h \
......@@ -247,6 +249,8 @@ libpoppler_la_SOURCES = \
PreScanOutputDev.cc \
PSTokenizer.cc \
Rendition.cc \
SignatureHandler.cc \
SignatureInfo.cc \
StdinCachedFile.cc \
StdinPDFDocBuilder.cc \
Stream.cc \
......@@ -275,6 +279,7 @@ libpoppler_la_CPPFLAGS = \
$(libjpeg2000_includes) \
$(libpng_includes) \
$(libcurl_includes) \
$(NSS3_CFLAGS) \
$(FREETYPE_CFLAGS) \
$(FONTCONFIG_CFLAGS) \
$(AM_CPPFLAGS)
......@@ -290,6 +295,7 @@ libpoppler_la_LIBADD = \
$(zlib_libs) \
$(libcurl_libs) \
$(libjpeg2000_libs) \
$(NSS3_LIBS) \
$(FREETYPE_LIBS) \
$(FONTCONFIG_LIBS) \
$(PTHREAD_LIBS) \
......
......@@ -32,6 +32,8 @@
// Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
// Copyright (C) 2014 Bogdan Cristea <cristeab@gmail.com>
// Copyright (C) 2015 Li Junling <lijunling@sina.com>
// Copyright (C) 2015 André Guerreiro <aguerreiro1985@gmail.com>
// Copyright (C) 2015 André Esser <bepandre@hotmail.com>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
......@@ -76,6 +78,8 @@
#endif
#include "PDFDoc.h"
#include "Hints.h"
#include "DateInfo.h"
#include "SignatureHandler.h"
#if MULTITHREADED
# define pdfdocLocker() MutexLocker locker(&mutex)
......@@ -452,6 +456,29 @@ GBool PDFDoc::checkEncryption(GooString *ownerPassword, GooString *userPassword)
return ret;
}
unsigned int PDFDoc::countSignatures()
{
return getSignatureWidgets().size();
}
std::vector<FormWidgetSignature*> PDFDoc::getSignatureWidgets()
{
int num_pages = getNumPages();
FormPageWidgets *page_widgets = NULL;
std::vector<FormWidgetSignature*> widget_vector;
for (int i = 1; i <= num_pages; i++) {
page_widgets = getCatalog()->getPage(i)->getFormWidgets();
for (int j = 0; page_widgets != NULL && j < page_widgets->getNumWidgets(); j++) {
if (page_widgets->getWidget(j)->getType() == formSignature) {
widget_vector.push_back(static_cast<FormWidgetSignature*>(page_widgets->getWidget(j)));
}
}
delete page_widgets;
}
return widget_vector;
}
void PDFDoc::displayPage(OutputDev *out, int page,
double hDPI, double vDPI, int rotate,
GBool useMediaBox, GBool crop, GBool printing,
......
......@@ -27,6 +27,8 @@
// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
// Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
// Copyright (C) 2013 Adrian Perez de Castro <aperez@igalia.com>
// Copyright (C) 2015 André Guerreiro <aguerreiro1985@gmail.com>
// Copyright (C) 2015 André Esser <bepandre@hotmail.com>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
......@@ -47,8 +49,11 @@
#include "Catalog.h"
#include "Page.h"
#include "Annot.h"
#include "Form.h"
#include "OptionalContent.h"
#include "Stream.h"
#include "poppler-config.h"
#include "SignatureInfo.h"
class GooString;
class GooFile;
......@@ -62,6 +67,7 @@ class Linearization;
class SecurityHandler;
class Hints;
class StructTreeRoot;
class SignatureHandler;
enum PDFWriteMode {
writeStandard,
......@@ -199,6 +205,9 @@ public:
// Is the file encrypted?
GBool isEncrypted() { return xref->isEncrypted(); }
unsigned int countSignatures();
std::vector<FormWidgetSignature*> getSignatureWidgets();
// Check various permissions.
GBool okToPrint(GBool ignoreOwnerPW = gFalse)
{ return xref->okToPrint(ignoreOwnerPW); }
......
//========================================================================
//
// SignatureHandler.cc
//
// This file is licensed under the GPLv2 or later
//
// Copyright 2015 André Guerreiro <aguerreiro1985@gmail.com>
// Copyright 2015 André Esser <bepandre@hotmail.com>
//
//========================================================================
#include <config.h>
#include "SignatureHandler.h"
#include "goo/GooString.h"
#include "goo/gmem.h"
#include <dirent.h>
#include <Error.h>
void SignatureHandler::digestFile(unsigned char *digest_buffer, unsigned char *input_data, int input_data_len, SECOidTag hashOIDTag)
{
HASH_HashType hashType;
hashType = HASH_GetHashTypeByOidTag(hashOIDTag);
HASH_HashBuf(hashType, digest_buffer, input_data, input_data_len);
}
unsigned int SignatureHandler::digestLength(SECOidTag digestAlgId)
{
switch(digestAlgId){
case SEC_OID_SHA1:
return 20;
case SEC_OID_SHA256:
return 32;
case SEC_OID_SHA384:
return 48;
case SEC_OID_SHA512:
return 64;
default:
printf("ERROR: Unrecognized Hash ID\n");
return 0;
}
}
char *SignatureHandler::getSignerName()
{
if (!CMSSignerInfo)
return NULL;
CERTCertificate *cert = NSS_CMSSignerInfo_GetSigningCertificate(CMSSignerInfo, CERT_GetDefaultCertDB());
return CERT_GetCommonName(&cert->subject);
}
time_t SignatureHandler::getSigningTime()
{
PRTime sTime; // time in microseconds since the epoch
if (NSS_CMSSignerInfo_GetSigningTime (CMSSignerInfo, &sTime) != SECSuccess)
return 0;
return (time_t) sTime/1000000;
}
GooString *SignatureHandler::getDefaultFirefoxCertDB_Linux()
{
GooString * finalPath = NULL;
DIR *toSearchIn;
struct dirent *subFolder;
GooString * homePath = new GooString(getenv("HOME"));
homePath = homePath->append("/.mozilla/firefox/");
if ((toSearchIn = opendir(homePath->getCString())) == NULL) {
error(errInternal, 0, "couldn't find default Firefox Folder");
return NULL;
}
do {
if ((subFolder = readdir(toSearchIn)) != NULL) {
if (strstr(subFolder->d_name, "default") != NULL) {
finalPath = homePath->append(subFolder->d_name);
closedir(toSearchIn);
return finalPath;
}
}
} while (subFolder != NULL);
return NULL;
}
/**
* Initialise NSS
*/
void SignatureHandler::init_nss()
{
GooString *certDBPath = getDefaultFirefoxCertDB_Linux();
if (certDBPath == NULL) {
NSS_Init("sql:/etc/pki/nssdb");
} else {
NSS_Init(certDBPath->getCString());
}
if (certDBPath) {
delete certDBPath;
}
}
SignatureHandler::SignatureHandler(unsigned char *p7, int p7_length)
{
init_nss();
CMSitem.data = p7;
CMSitem.len = p7_length;
CMSMessage = CMS_MessageCreate(&CMSitem);
CMSSignedData = CMS_SignedDataCreate(CMSMessage);
CMSSignerInfo = CMS_SignerInfoCreate(CMSSignedData);
}
SignatureHandler::~SignatureHandler()
{
SECITEM_FreeItem(&CMSitem, PR_FALSE);
if (CMSSignerInfo)
NSS_CMSSignerInfo_Destroy(CMSSignerInfo);
if (CMSSignedData)
NSS_CMSSignedData_Destroy(CMSSignedData);
if (CMSMessage)
NSS_CMSMessage_Destroy(CMSMessage);
free(temp_certs);
if (NSS_Shutdown()!=SECSuccess)
fprintf(stderr, "Detail: %s\n", PR_ErrorToString(PORT_GetError(), PR_LANGUAGE_I_DEFAULT));
}
NSSCMSMessage *SignatureHandler::CMS_MessageCreate(SECItem * cms_item)
{
if (cms_item->data){
return NSS_CMSMessage_CreateFromDER(cms_item, NULL, NULL /* Content callback */
, NULL, NULL /*Password callback*/
, NULL, NULL /*Decrypt callback*/);
} else {
return NULL;
}
}
NSSCMSSignedData *SignatureHandler::CMS_SignedDataCreate(NSSCMSMessage * cms_msg)
{
if (!NSS_CMSMessage_IsSigned(cms_msg)) {
error(errInternal, 0, "Input couldn't be parsed as a CMS signature");
return NULL;
}
NSSCMSContentInfo *cinfo = NSS_CMSMessage_ContentLevel(cms_msg, 0);
if (!cinfo) {
error(errInternal, 0, "Error in NSS_CMSMessage_ContentLevel");
return NULL;
}
NSSCMSSignedData *signedData = (NSSCMSSignedData*) NSS_CMSContentInfo_GetContent(cinfo);
if (!signedData) {
error(errInternal, 0, "CError in NSS_CMSContentInfo_GetContent()");
return NULL;
}
if (signedData->rawCerts)
{
size_t i;
for (i = 0; signedData->rawCerts[i]; ++i) {} // just count the length of the certificate chain
// tempCerts field needs to be filled for complete memory release by NSSCMSSignedData_Destroy
signedData->tempCerts = (CERTCertificate **) gmallocn( i+1, sizeof(CERTCertificate *));
memset(signedData->tempCerts, 0, (i+1) * sizeof(CERTCertificate *));
// store the adresses of these temporary certificates for future release
for (i = 0; signedData->rawCerts[i]; ++i)
signedData->tempCerts[i] = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), signedData->rawCerts[i], NULL, 0, 0);
temp_certs = signedData->tempCerts;
return signedData;
} else {
return NULL;
}
}
NSSCMSSignerInfo *SignatureHandler::CMS_SignerInfoCreate(NSSCMSSignedData * cms_sig_data)
{
NSSCMSSignerInfo *signerInfo = NSS_CMSSignedData_GetSignerInfo(cms_sig_data, 0);
if (!signerInfo) {
printf("Error in NSS_CMSSignedData_GetSignerInfo()\n");
return NULL;
} else {
return signerInfo;
}
}
NSSCMSVerificationStatus SignatureHandler::ValidateSignature(unsigned char *signed_data, int signed_data_len)
{
unsigned char *digest_buffer = NULL;
if (!CMSSignedData)
return NSSCMSVS_MalformedSignature;
SECItem usedAlgorithm = NSS_CMSSignedData_GetDigestAlgs(CMSSignedData)[0]->algorithm;
unsigned int hash_length = digestLength(SECOID_FindOIDTag(&usedAlgorithm));
digest_buffer = (unsigned char *)PORT_Alloc(hash_length);
digestFile(digest_buffer, signed_data, signed_data_len, SECOID_FindOIDTag(&usedAlgorithm));
SECItem digest;
digest.data = digest_buffer;
digest.len = hash_length;
if ((NSS_CMSSignerInfo_GetSigningCertificate(CMSSignerInfo, CERT_GetDefaultCertDB())) == NULL)
CMSSignerInfo->verificationStatus = NSSCMSVS_SigningCertNotFound;
if (NSS_CMSSignerInfo_Verify(CMSSignerInfo, &digest, NULL) != SECSuccess) {
PORT_Free(digest_buffer);
return CMSSignerInfo->verificationStatus;
} else {
PORT_Free(digest_buffer);
return NSSCMSVS_GoodSignature;
}
}
SECErrorCodes SignatureHandler::ValidateCertificate()
{
SECErrorCodes retVal;
CERTCertificate *cert;
if (!CMSSignerInfo)
return (SECErrorCodes) -1; //error code to avoid matching error codes defined in SECErrorCodes
if ((cert = NSS_CMSSignerInfo_GetSigningCertificate(CMSSignerInfo, CERT_GetDefaultCertDB())) == NULL)
CMSSignerInfo->verificationStatus = NSSCMSVS_SigningCertNotFound;
CERTValInParam inParams[2];
inParams[0].type = cert_pi_revocationFlags;
inParams[0].value.pointer.revocation = CERT_GetClassicOCSPEnabledSoftFailurePolicy();
inParams[1].type = cert_pi_end;
if (CERT_PKIXVerifyCert(cert, certificateUsageEmailSigner, inParams, NULL,
CMSSignerInfo->cmsg->pwfn_arg) != SECSuccess) {
retVal = (SECErrorCodes) PORT_GetError();
} else {
// PORT_GetError() will return 0 if everything was fine,
// there are other possible outcomes even if the previous return was SECSuccess.
retVal = (SECErrorCodes) PORT_GetError();
}
if (cert)
CERT_DestroyCertificate(cert);
return retVal;
}
SignatureValidationStatus SignatureHandler::NSS_SigTranslate(NSSCMSVerificationStatus nss_code)
{
switch(nss_code)
{
case NSSCMSVS_GoodSignature:
return SIGNATURE_VALID;
case NSSCMSVS_BadSignature:
return SIGNATURE_INVALID;
case NSSCMSVS_DigestMismatch:
return SIGNATURE_DIGEST_MISMATCH;
case NSSCMSVS_ProcessingError:
return SIGNATURE_DECODING_ERROR;
default:
return SIGNATURE_GENERIC_ERROR;
}
}
CertificateValidationStatus SignatureHandler::NSS_CertTranslate(SECErrorCodes nss_code)
{
// 0 not defined in SECErrorCodes, it means success for this purpose.
if (nss_code == (SECErrorCodes) 0)
return CERTIFICATE_TRUSTED;
switch(nss_code)
{
case SEC_ERROR_UNKNOWN_ISSUER:
return CERTIFICATE_UNTRUSTED;
case SEC_ERROR_REVOKED_CERTIFICATE:
return CERTIFICATE_REVOKED;
case SEC_ERROR_EXPIRED_CERTIFICATE:
return CERTIFICATE_EXPIRED;
default:
return CERTIFICATE_GENERIC_ERROR;
}
}
//========================================================================
//
// SignatureHandler.h
//