/*
* Copyright (C) 2014 Intel Corporation
* All rights reserved.
*/
package com.intel.mtwilson.tls.policy.creator.impl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.intel.dcsg.cpg.codec.ByteArrayCodec;
import com.intel.dcsg.cpg.crypto.CryptographyException;
import com.intel.dcsg.cpg.crypto.digest.Digest;
import com.intel.dcsg.cpg.crypto.digest.DigestUtil;
import com.intel.dcsg.cpg.crypto.digest.UnsupportedAlgorithmException;
import com.intel.dcsg.cpg.tls.policy.impl.PublicKeyDigestTlsPolicy;
import com.intel.dcsg.cpg.x509.repository.DigestRepository;
import com.intel.dcsg.cpg.x509.repository.HashSetMutableDigestRepository;
import com.intel.mtwilson.tls.policy.TlsPolicyDescriptor;
import com.intel.mtwilson.tls.policy.factory.TlsPolicyCreator;
import com.intel.mtwilson.tls.policy.factory.TlsPolicyFactoryUtil;
/**
*
* @author jbuhacoff
*/
public class PublicKeyDigestTlsPolicyCreator implements TlsPolicyCreator {
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(PublicKeyDigestTlsPolicyCreator.class);
@Override
public PublicKeyDigestTlsPolicy createTlsPolicy(TlsPolicyDescriptor tlsPolicyDescriptor) {
if( "public-key-digest".equalsIgnoreCase(tlsPolicyDescriptor.getPolicyType()) ) {
try {
DigestRepository repository = getPublicKeyDigestRepository(tlsPolicyDescriptor);
return new PublicKeyDigestTlsPolicy(repository);
}
catch(CryptographyException e) {
throw new IllegalArgumentException("Cannot create public key digest policy from given repository", e);
}
}
return null;
}
private DigestRepository getPublicKeyDigestRepository(TlsPolicyDescriptor tlsPolicyDescriptor) throws CryptographyException {
HashSetMutableDigestRepository repository = new HashSetMutableDigestRepository();
if( "public-key-digest".equals(tlsPolicyDescriptor.getPolicyType())) {
if( tlsPolicyDescriptor.getData() == null || tlsPolicyDescriptor.getData().isEmpty() ) {
throw new IllegalArgumentException("TLS policy descriptor does not contain any certificate digests");
}
ByteArrayCodec codec;
PublicKeyDigestMetadata meta = getPublicKeyDigestMetadata(tlsPolicyDescriptor);
if( meta.digestEncoding == null ) {
// attempt auto-detection based on first digest
String sample = TlsPolicyFactoryUtil.getFirst(tlsPolicyDescriptor.getData());
meta.digestEncoding = TlsPolicyFactoryUtil.guessEncodingForData(sample);
log.debug("Guessing codec {} for sample data {}", meta.digestEncoding, sample);
}
codec = TlsPolicyFactoryUtil.getCodecByName(meta.digestEncoding); // safe because if input is null return value will be null
if( codec == null ) {
throw new IllegalArgumentException("TlsPolicyDescriptor indicates public key digests but does not declare digest encoding");
}
log.debug("Codec {} for digest encoding {}", codec.getClass().getName(), meta.digestEncoding);
String alg;
if( meta.digestAlgorithm == null || meta.digestAlgorithm.isEmpty() ) {
// attempt auto-detection based on first digest
String sample = TlsPolicyFactoryUtil.getFirst(tlsPolicyDescriptor.getData());
byte[] hash = codec.decode(sample);
alg = TlsPolicyFactoryUtil.guessAlgorithmForDigest(hash);
}
else {
alg = meta.digestAlgorithm;
}
if( alg == null ) {
throw new IllegalArgumentException("TlsPolicyDescriptor indicates public key digests but does not declare digest algorithm");
}
alg = DigestUtil.getJavaAlgorithmName(alg);
if( alg == null ) {
throw new UnsupportedAlgorithmException(alg);
}
for(String publicKeyDigest : tlsPolicyDescriptor.getData()) {
Digest digest = new Digest(alg, codec.decode(publicKeyDigest));
repository.addDigest(digest);
}
return repository;
}
return null;
}
/**
*
* @param tlsPolicyDescriptor
* @return an instance of CertificateDigestMetadata, but some fields may be null if they were not included in the descriptor's meta section
*/
public static PublicKeyDigestMetadata getPublicKeyDigestMetadata(TlsPolicyDescriptor tlsPolicyDescriptor) {
PublicKeyDigestMetadata metadata = new PublicKeyDigestMetadata();
if( tlsPolicyDescriptor.getMeta() == null ) {
return metadata;
}
if(tlsPolicyDescriptor.getMeta() == null) {
throw new IllegalArgumentException("TLS policy descriptor metadata cannot be null.");
}
if( tlsPolicyDescriptor.getMeta().get("digestEncoding") != null && !tlsPolicyDescriptor.getMeta().get("digestEncoding").isEmpty() ) {
metadata.digestEncoding = tlsPolicyDescriptor.getMeta().get("digestEncoding");
}
if( tlsPolicyDescriptor.getMeta().get("digestAlgorithm") != null && !tlsPolicyDescriptor.getMeta().get("digestAlgorithm").isEmpty() ) {
metadata.digestAlgorithm = tlsPolicyDescriptor.getMeta().get("digestAlgorithm");
}
return metadata;
}
public static class PublicKeyDigestMetadata {
public String digestAlgorithm;
public String digestEncoding;
}
}