/*******************************************************************************
* Copyright 2014 by E-Government Innovation Center EGIZ, Graz, Austria
* PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
* joint initiative of the Federal Chancellery Austria and Graz University of
* Technology.
*
* Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
* the European Commission - subsequent versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
* http://www.osor.eu/eupl/
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Licence is distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*
* This product combines work with different licenses. See the "NOTICE" text
* file for details on the various modules and licenses.
* The "NOTICE" text file is part of the distribution. Any derivative works
* that you distribute must include a readable copy of the "NOTICE" text file.
******************************************************************************/
package at.gv.egiz.pdfas.lib.api;
import iaik.security.ec.provider.ECCelerate;
import iaik.security.provider.IAIK;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import java.security.Provider;
import java.security.Security;
import java.util.Map;
import java.util.Map.Entry;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.activation.DataSource;
import javax.crypto.Cipher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import at.gv.egiz.pdfas.common.exceptions.PdfAsSettingsException;
import at.gv.egiz.pdfas.common.exceptions.PdfAsSettingsValidationException;
import at.gv.egiz.pdfas.common.settings.ISettings;
import at.gv.egiz.pdfas.lib.api.sign.SignParameter;
import at.gv.egiz.pdfas.lib.api.verify.VerifyParameter;
import at.gv.egiz.pdfas.lib.configuration.ConfigurationValidator;
import at.gv.egiz.pdfas.lib.impl.PdfAsImpl;
import at.gv.egiz.pdfas.lib.impl.SignParameterImpl;
import at.gv.egiz.pdfas.lib.impl.VerifyParameterImpl;
import at.gv.egiz.pdfas.lib.impl.configuration.ConfigValidatorLoader;
public class PdfAsFactory implements IConfigurationConstants {
private static final Logger logger = LoggerFactory
.getLogger(PdfAsFactory.class);
private static final String DEFAULT_CONFIG_RES = "config/config.zip";
protected static void registerProvider(Provider provider, int position) {
String name = provider.getName();
if (Security.getProvider(name) == null) {
// register IAIK provider at first position
try {
if (position < 0) {
// add provider add default position.
Security.addProvider(provider);
} else {
Security.insertProviderAt(provider, position);
}
} catch (SecurityException e) {
logger.info("Failed to register required security Provider.", e);
}
} else {
logger.info("Required security Provider {} already registered.",
name);
}
}
protected static void listRegisteredSecurityProviders() {
Provider[] providers = Security.getProviders();
logger.debug("Registered Security Providers:");
for (int i = 0; i < providers.length; i++) {
logger.debug(" {}: {} => {}", i, providers[i].getName(),
providers[i].getInfo());
}
}
private static boolean initialized = false;
private static Object init_mutex = new Object();
private static void registerSecurityProvider(ISettings configuration) {
boolean doRegister = true;
String register = configuration.getValue(REGISTER_PROVIDER);
if (register != null) {
if (register.equals("false")) {
doRegister = false;
}
}
if (doRegister) {
logger.info("Registering Security Providers!");
registerProvider(new IAIK(), 1);
// TODO: register ECCelerate in second position when TLS issue is
// fixed
registerProvider(new ECCelerate(), -1);
} else {
logger.info("Skipping Security Provider registration!");
}
}
private static void teeInformation(String str) {
// System.out.println(str);
logger.info(str);
}
private static void showRuntimeInformation() {
try {
RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
OperatingSystemMXBean osBean = ManagementFactory
.getOperatingSystemMXBean();
teeInformation("+ OS Name: " + osBean.getName());
teeInformation("+ OS Version: " + osBean.getVersion());
teeInformation("+ OS Arch: " + osBean.getArch());
teeInformation("+ JAVA Version: "
+ runtimeBean.getSystemProperties().get(
"java.runtime.version"));
teeInformation("+ JAVA Spec ----------------------------------------------------------");
teeInformation("+ JAVA Spec Name: " + runtimeBean.getSpecName());
teeInformation("+ JAVA Spec Version: "
+ runtimeBean.getSpecVersion());
teeInformation("+ JAVA Spec Vendor: " + runtimeBean.getSpecVendor());
teeInformation("+ JAVA VM ----------------------------------------------------------");
teeInformation("+ JAVA VM Name: " + runtimeBean.getVmName());
teeInformation("+ JAVA VM Version: " + runtimeBean.getVmVersion());
teeInformation("+ JAVA VM Vendor: " + runtimeBean.getVmVendor());
teeInformation("+ AES Max allowed Key Length: "
+ Cipher.getMaxAllowedKeyLength("AES"));
teeInformation("+ RSA Max allowed Key Length: "
+ Cipher.getMaxAllowedKeyLength("RSA"));
teeInformation("+ EC Max allowed Key Length: "
+ Cipher.getMaxAllowedKeyLength("EC"));
teeInformation("+ DSA Max allowed Key Length: "
+ Cipher.getMaxAllowedKeyLength("DSA"));
} catch (Throwable e) {
teeInformation("+ Failed to show runtime informations");
}
}
private static void showSecProviderInfo() {
try {
teeInformation("+ IAIK-JCE Version: " + IAIK.getVersionInfo());
teeInformation("+ ECCelerate Version: "
+ ECCelerate.getInstance().getVersion());
} catch (Throwable e) {
teeInformation("+ Failed to show security provider informations");
}
}
/**
* Configure log.
*
* @param configuration
* the configuration
*/
private static void initialize(ISettings configuration) {
if (!initialized) {
synchronized (init_mutex) {
if (!initialized) {
initialized = true;
registerGraphicsEnvironment();
registerSecurityProvider(configuration);
teeInformation("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
teeInformation("+ PDF-AS: " + getVersion());
teeInformation("+ PDF-AS SCM Revision: " + getSCMRevision());
showRuntimeInformation();
showSecProviderInfo();
teeInformation("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
listRegisteredSecurityProviders();
}
}
}
}
private static void registerGraphicsEnvironment(){
BufferedImage bim = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = bim.createGraphics();
}
/**
* Create a new instance of PDF-AS
*
* @param configuration
* The PDF-AS configuration
* @return
*/
public static PdfAs createPdfAs(File configuration) {
PdfAs pdfas = new PdfAsImpl(configuration);
if (!initialized) {
synchronized (init_mutex) {
initialize((ISettings) pdfas.getConfiguration());
}
}
return pdfas;
}
/**
* Creates a new PdfAs object.
*
* @param settings
* the settings
* @return the pdf as
*/
public static PdfAs createPdfAs(ISettings settings) {
if (!initialized) {
synchronized (init_mutex) {
initialize(settings);
}
}
return new PdfAsImpl(settings);
}
/**
* Creates a sign parameter
*
* @param configuration
* The configuration to be used
* @param dataSource
* The data source to be used
* @return
*/
public static SignParameter createSignParameter(
Configuration configuration, DataSource dataSource,
OutputStream output) {
SignParameter param = new SignParameterImpl(configuration, dataSource,
output);
return param;
}
/**
* Creates a verification parameter
*
* @param configuration
* The configuration to be used
* @param dataSource
* The data source to be used
* @return
*/
public static VerifyParameter createVerifyParameter(
Configuration configuration, DataSource dataSource) {
VerifyParameter param = new VerifyParameterImpl(configuration,
dataSource);
return param;
}
/**
* Deploy default configuration to targetDirectory
*
* The targetDirectory will be deleted and
*
* @param targetDirectory
* @throws Exception
*/
public static void deployDefaultConfiguration(File targetDirectory)
throws Exception {
if (targetDirectory.exists()) {
targetDirectory.delete();
}
if (!targetDirectory.exists()) {
targetDirectory.mkdir();
}
InputStream is = ClassLoader
.getSystemResourceAsStream(DEFAULT_CONFIG_RES);
ZipInputStream zip = null;
try {
zip = new ZipInputStream(is);
ZipEntry entry = zip.getNextEntry();
while (entry != null) {
File destinationPath = new File(
targetDirectory.getAbsolutePath(), entry.getName());
// create parent directories
destinationPath.getParentFile().mkdirs();
// if the entry is a file extract it
if (entry.isDirectory()) {
destinationPath.mkdir();
zip.closeEntry();
entry = zip.getNextEntry();
continue;
} else {
logger.debug("Extracting file: " + destinationPath);
int b;
byte buffer[] = new byte[1024];
FileOutputStream fos = new FileOutputStream(destinationPath);
BufferedOutputStream bos = new BufferedOutputStream(fos,
1024);
while ((b = zip.read(buffer, 0, 1024)) != -1) {
bos.write(buffer, 0, b);
}
bos.close();
zip.closeEntry();
}
entry = zip.getNextEntry();
}
} catch (IOException ioe) {
System.out.println("Error opening zip file" + ioe);
} finally {
try {
if (zip != null) {
zip.close();
}
} catch (IOException ioe) {
System.out.println("Error while closing zip file" + ioe);
}
}
}
/**
* Gets the PDF-AS SCM Revision
*
* @return
*/
public static String getSCMRevision() {
Package pack = PdfAsFactory.class.getPackage();
return pack.getSpecificationVersion();
}
/**
* Gets the PDF-AS Version
*
* @return PDF-AS Verison string
*/
public static String getVersion() {
Package pack = PdfAsFactory.class.getPackage();
return pack.getImplementationVersion();
}
/**
* Execute all loaded Configuration Validators
*
* @throws PdfAsSettingsValidationException
*/
public static void validateConfiguration(ISettings configuration) throws PdfAsSettingsValidationException{
Map availableValidators = ConfigValidatorLoader.getAvailableValidators();
if(availableValidators.isEmpty()){
logger.info("No configuration validators available");
}
for(Entry validatorEntry : availableValidators.entrySet()){
logger.info("Running configuration validator: "+validatorEntry.getKey());
validatorEntry.getValue().validate(configuration);
}
logger.info("All configuration validators succeded.");
}
}