final SessionData sessionData,
final boolean requireProtection) throws Exception {
//
// Parse response message
//
final PKIMessage respObject = PKIMessage.getInstance(new ASN1InputStream(new ByteArrayInputStream(retMsg)).readObject());
if ( respObject==null ) {
StressTest.this.performanceTest.getLog().error("No command response message.");
return false;
}
// The signer, i.e. the CA, check it's the right CA
final PKIHeader header = respObject.getHeader();
if ( header==null ) {
StressTest.this.performanceTest.getLog().error("No header in response message.");
return false;
}
// Check that the signer is the expected CA
final X509Name name = X509Name.getInstance(header.getSender().getName());
if ( header.getSender().getTagNo()!=4 || name==null || !name.equals(this.cacert.getSubjectDN()) ) {
StressTest.this.performanceTest.getLog().error("Not signed by right issuer.");
}
if ( header.getSenderNonce().getOctets().length!=16 ) {
StressTest.this.performanceTest.getLog().error("Wrong length of received sender nonce (made up by server). Is "+header.getSenderNonce().getOctets().length+" byte but should be 16.");
}
if ( !Arrays.equals(header.getRecipNonce().getOctets(), sessionData.getNonce()) ) {
StressTest.this.performanceTest.getLog().error("recipient nonce not the same as we sent away as the sender nonce. Sent: "+Arrays.toString(sessionData.getNonce())+" Received: "+Arrays.toString(header.getRecipNonce().getOctets()));
}
if ( !Arrays.equals(header.getTransactionID().getOctets(), sessionData.getTransId()) ) {
StressTest.this.performanceTest.getLog().error("transid is not the same as the one we sent");
}
{
// Check that the message is signed with the correct digest alg
final AlgorithmIdentifier algId = header.getProtectionAlg();
if (algId==null || algId.getObjectId()==null || algId.getObjectId().getId()==null) {
if ( requireProtection ) {
StressTest.this.performanceTest.getLog().error("Not possible to get algorithm.");
return false;
}
return true;
}
final String id = algId.getObjectId().getId();
if ( id.equals(PKCSObjectIdentifiers.sha1WithRSAEncryption.getId()) ) {
if ( this.firstTime ) {
this.firstTime = false;
this.isSign = true;
StressTest.this.performanceTest.getLog().info("Signature protection used.");
} else if ( !this.isSign ) {
StressTest.this.performanceTest.getLog().error("Message password protected but should be signature protected.");
}
} else if ( id.equals(CMPObjectIdentifiers.passwordBasedMac.getId()) ) {
if ( this.firstTime ) {
this.firstTime = false;
this.isSign = false;
StressTest.this.performanceTest.getLog().info("Password (PBE) protection used.");
} else if ( this.isSign ) {
StressTest.this.performanceTest.getLog().error("Message signature protected but should be password protected.");
}
} else {
StressTest.this.performanceTest.getLog().error("No valid algorithm.");
return false;
}
}
if ( this.isSign ) {
// Verify the signature
byte[] protBytes = respObject.getProtectedBytes();
final DERBitString bs = respObject.getProtection();
final Signature sig;
try {
sig = Signature.getInstance(PKCSObjectIdentifiers.sha1WithRSAEncryption.getId());
sig.initVerify(this.cacert);
sig.update(protBytes);
if ( !sig.verify(bs.getBytes()) ) {
StressTest.this.performanceTest.getLog().error("CA signature not verifying");
}
} catch ( Exception e) {
StressTest.this.performanceTest.getLog().error("Not possible to verify signature.", e);
}
} else {
//final DEROctetString os = header.getSenderKID();
//if ( os!=null )
// StressTest.this.performanceTest.getLog().info("Found a sender keyId: "+new String(os.getOctets()));
// Verify the PasswordBased protection of the message
final PBMParameter pp; {
final AlgorithmIdentifier pAlg = header.getProtectionAlg();
// StressTest.this.performanceTest.getLog().info("Protection type is: "+pAlg.getObjectId().getId());
pp = PBMParameter.getInstance(pAlg.getParameters());
}
final int iterationCount = pp.getIterationCount().getPositiveValue().intValue();
// StressTest.this.performanceTest.getLog().info("Iteration count is: "+iterationCount);
final AlgorithmIdentifier owfAlg = pp.getOwf();
// Normal OWF alg is 1.3.14.3.2.26 - SHA1
// StressTest.this.performanceTest.getLog().info("Owf type is: "+owfAlg.getObjectId().getId());
final AlgorithmIdentifier macAlg = pp.getMac();
// Normal mac alg is 1.3.6.1.5.5.8.1.2 - HMAC/SHA1
// StressTest.this.performanceTest.getLog().info("Mac type is: "+macAlg.getObjectId().getId());
final byte[] salt = pp.getSalt().getOctets();
//log.info("Salt is: "+new String(salt));
final byte[] raSecret = new String("password").getBytes();
// HMAC/SHA1 os normal 1.3.6.1.5.5.8.1.2 or 1.2.840.113549.2.7
final String macOid = macAlg.getObjectId().getId();
final SecretKey key; {
byte[] basekey = new byte[raSecret.length + salt.length];
for (int i = 0; i < raSecret.length; i++) {
basekey[i] = raSecret[i];
}
for (int i = 0; i < salt.length; i++) {
basekey[raSecret.length+i] = salt[i];
}
// Construct the base key according to rfc4210, section 5.1.3.1
final MessageDigest dig = MessageDigest.getInstance(owfAlg.getObjectId().getId(), this.bcProvider);
for (int i = 0; i < iterationCount; i++) {
basekey = dig.digest(basekey);
dig.reset();
}
key = new SecretKeySpec(basekey, macOid);
}
final Mac mac = Mac.getInstance(macOid, this.bcProvider);
mac.init(key);
mac.reset();
final byte[] protectedBytes = respObject.getProtectedBytes();
final DERBitString protection = respObject.getProtection();
mac.update(protectedBytes, 0, protectedBytes.length);
byte[] out = mac.doFinal();
// My out should now be the same as the protection bits
byte[] pb = protection.getBytes();
if ( !Arrays.equals(out, pb) ) {