/*
* Copyright (C) 2014 Intel Corporation
* All rights reserved.
*/
package com.intel.mtwilson.trustagent.ws.v2;
import com.intel.dcsg.cpg.crypto.RandomUtil;
import com.intel.dcsg.cpg.net.IPv4Address;
import com.intel.dcsg.cpg.util.ByteArray;
import com.intel.mountwilson.common.TAException;
import com.intel.mountwilson.trustagent.commands.BuildQuoteXMLCmd;
import com.intel.mountwilson.trustagent.commands.CreateNonceFileCmd;
import com.intel.mountwilson.trustagent.commands.GenerateModulesCmd;
import com.intel.mountwilson.trustagent.commands.GenerateQuoteCmd;
import com.intel.mountwilson.trustagent.commands.ReadIdentityCmd;
import com.intel.mountwilson.trustagent.data.TADataContext;
import com.intel.mtwilson.My;
import com.intel.mtwilson.launcher.ws.ext.V2;
import com.intel.dcsg.cpg.crypto.Sha1Digest;
import com.intel.mountwilson.common.CommandUtil;
import com.intel.mountwilson.common.ErrorCode;
import com.intel.mtwilson.trustagent.TrustagentConfiguration;
import com.intel.mtwilson.trustagent.TrustagentRepository;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.intel.mtwilson.trustagent.model.TpmQuoteRequest;
import com.intel.mtwilson.trustagent.model.TpmQuoteResponse;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
/**
*
* @author jbuhacoff
*/
@V2
@Path("/tpm")
public class Tpm {
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Tpm.class);
/*
@POST
@Path("/quote")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public byte[] tpmQuoteBytes(TpmQuoteRequest tpmQuoteRequest, @Context HttpServletRequest request) throws IOException, TAException {
return null;
}
*/
@POST
@Path("/quote")
@Consumes({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
public TpmQuoteResponse tpmQuote(TpmQuoteRequest tpmQuoteRequest, @Context HttpServletRequest request) throws IOException, TAException {
/**
* issue #1038 we will hash this ip address together with the input
* nonce to produce the quote nonce; mtwilson server will do the same
* thing; this prevents a MITM "quote relay" attack where an attacker
* can accept quote requests at host A, forward them to trusted host B,
* and then reply with host B's quote to the challenger (same nonce etc)
* because with this fix mtwilson is hashing host A's ip address into
* the nonce on its end, and host B is hashing its ip address into the
* nonce (here), so the quote will fail the challenger's verification
* because of the different nonces; Attacker will also not be able to
* cheat by hashing host B's ip address into the nonce because host B
* will again has its ip address so it will be double-hashed and fail
* verification
*/
TrustagentConfiguration configuration = TrustagentConfiguration.loadConfiguration();
if( configuration.isTpmQuoteWithIpAddress() ) {
if( IPv4Address.isValid(request.getLocalAddr()) ) {
IPv4Address ipv4 = new IPv4Address(request.getLocalAddr());
byte[] extendedNonce = Sha1Digest.digestOf(tpmQuoteRequest.getNonce()).extend(ipv4.toByteArray()).toByteArray(); // again 20 bytes
tpmQuoteRequest.setNonce(extendedNonce);
}
else {
log.debug("Local address is {}", request.getLocalAddr());
throw new WebApplicationException(Response.serverError().header("Error", "tpm.quote.ipv4 enabled but local address not IPv4").build());
}
}
TADataContext context = new TADataContext(); // when we call getSessionId it will create a new random one
context.setNonce(Base64.encodeBase64String(tpmQuoteRequest.getNonce()));
context.setSelectedPCRs(joinIntegers(tpmQuoteRequest.getPcrs(), ' '));
new CreateNonceFileCmd(context).execute(); // FileUtils.write to file nonce (binary)
new ReadIdentityCmd(context).execute(); // trustagentrepository.getaikcertificate
// Get the module information
new GenerateModulesCmd(context).execute(); // String moduleXml = getXmlFromMeasureLog(configuration);
new GenerateQuoteCmd(context).execute();
new BuildQuoteXMLCmd(context).execute();
// return context.getResponseXML();
TpmQuoteResponse response = context.getTpmQuoteResponse();
// delete temporary session directory
CommandUtil.runCommand(String.format("rm -rf %s",
CommandUtil.doubleQuoteEscapeShellArgument(context.getDataFolder())));
return response;
}
private String joinIntegers(int[] pcrs, char separator) {
String[] array = new String[pcrs.length];
for(int i=0; i<pcrs.length; i++) {
array[i] = String.valueOf(pcrs[i]);
}
return StringUtils.join(array, separator);
}
}