org.eclipse.osgi_3.8.2.v20130124-134944

    {
      X509Certificate x509Cert = (X509Certificate)certs[i];
      sb.append(x509Cert.getSubjectDN().getName());
      sb.append("; ");
    }
    return sb.toString();
  }
  
  public Certificate getRoot()
  {
    Certificate[] certs = getCertificates();
    return certs.length > 0 ? certs[(certs.length - 1)] : null;
  }
  
  public Certificate getSigner()
  {
    Certificate[] certs = getCertificates();
    return certs.length > 0 ? certs[0] : null;
  }
  
  public Date getSigningTime()
  {
    return content.getSigningTime(signerInfo);
  }
  
  public boolean isTrusted()
  {
    return signerInfo.isTrusted();
  }
}

/* Location:
 * Qualified Name:     org.eclipse.osgi.internal.signedcontent.LegacyVerifierFactory.LegacyChain
 * Java Class Version: 1.4 (48.0)
 * JD-Core Version:    0.7.1
 */
package org.eclipse.osgi.internal.signedcontent;

import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.osgi.internal.provisional.verifier.CertificateChain;
import org.eclipse.osgi.internal.provisional.verifier.CertificateVerifier;
import org.eclipse.osgi.signedcontent.InvalidContentException;
import org.eclipse.osgi.signedcontent.SignedContent;
import org.eclipse.osgi.signedcontent.SignedContentEntry;
import org.eclipse.osgi.signedcontent.SignerInfo;

class LegacyVerifierFactory$LegacyVerifier
  implements CertificateVerifier
{
  private final SignedContent signedContent;
  
  public LegacyVerifierFactory$LegacyVerifier(SignedContent signedContent)
  {
    this.signedContent = signedContent;
  }
  
  public void checkContent()
    throws CertificateException, CertificateExpiredException
  {
    SignedContentEntry[] entries = signedContent.getSignedEntries();
    for (int i = 0; i < entries.length; i++) {
      try
      {
        entries[i].verify();
      }
      catch (InvalidContentException e)
      {
        throw ((SecurityException)new SecurityException(e.getMessage()).initCause(e));
      }
      catch (IOException e)
      {
        throw ((SecurityException)new SecurityException(e.getMessage()).initCause(e));
      }
    }
    SignerInfo[] infos = signedContent.getSignerInfos();
    for (int i = 0; i < infos.length; i++) {
      signedContent.checkValidity(infos[i]);
    }
  }
  
  public CertificateChain[] getChains()
  {
    SignerInfo[] infos = signedContent.getSignerInfos();
    CertificateChain[] chains = new CertificateChain[infos.length];
    for (int i = 0; i < chains.length; i++) {
      chains[i] = new LegacyVerifierFactory.LegacyChain(infos[i], signedContent);
    }
    return chains;
  }
  
  public boolean isSigned()
  {
    return signedContent.isSigned();
  }
  
  public String[] verifyContent()
  {
    List<String> invalidContent = new ArrayList(0);
    SignedContentEntry[] entries = signedContent.getSignedEntries();
    for (int i = 0; i < entries.length; i++) {
      try
      {
        entries[i].verify();
      }
      catch (InvalidContentException localInvalidContentException)
      {
        invalidContent.add(entries[i].getName());
      }
      catch (IOException localIOException)
      {
        invalidContent.add(entries[i].getName());
      }
    }
    return (String[])invalidContent.toArray(new String[invalidContent.size()]);
  }
}

/* Location:
 * Qualified Name:     org.eclipse.osgi.internal.signedcontent.LegacyVerifierFactory.LegacyVerifier
 * Java Class Version: 1.4 (48.0)
 * JD-Core Version:    0.7.1
 */
package org.eclipse.osgi.internal.signedcontent;

import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.Principal;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.eclipse.osgi.internal.provisional.verifier.CertificateChain;
import org.eclipse.osgi.internal.provisional.verifier.CertificateVerifier;
import org.eclipse.osgi.internal.provisional.verifier.CertificateVerifierFactory;
import org.eclipse.osgi.signedcontent.InvalidContentException;
import org.eclipse.osgi.signedcontent.SignedContent;
import org.eclipse.osgi.signedcontent.SignedContentEntry;
import org.eclipse.osgi.signedcontent.SignedContentFactory;
import org.eclipse.osgi.signedcontent.SignerInfo;
import org.osgi.framework.Bundle;

public class LegacyVerifierFactory
  implements CertificateVerifierFactory
{
  private final SignedContentFactory signedContentFactory;
  
  public LegacyVerifierFactory(SignedContentFactory signedContentFactory)
  {
    this.signedContentFactory = signedContentFactory;
  }
  
  public CertificateVerifier getVerifier(File content)
    throws IOException
  {
    try
    {
      return new LegacyVerifier(signedContentFactory.getSignedContent(content));
    }
    catch (GeneralSecurityException e)
    {
      throw ((IOException)new IOException(e.getMessage()).initCause(e));
    }
  }
  
  public CertificateVerifier getVerifier(Bundle bundle)
    throws IOException
  {
    try
    {
      return new LegacyVerifier(signedContentFactory.getSignedContent(bundle));
    }
    catch (GeneralSecurityException e)
    {
      throw ((IOException)new IOException(e.getMessage()).initCause(e));
    }
  }
  
  static class LegacyVerifier
    implements CertificateVerifier
  {
    private final SignedContent signedContent;
    
    public LegacyVerifier(SignedContent signedContent)
    {
      this.signedContent = signedContent;
    }
    
    public void checkContent()
      throws CertificateException, CertificateExpiredException
    {
      SignedContentEntry[] entries = signedContent.getSignedEntries();
      for (int i = 0; i < entries.length; i++) {
        try
        {
          entries[i].verify();
        }
        catch (InvalidContentException e)
        {
          throw ((SecurityException)new SecurityException(e.getMessage()).initCause(e));
        }
        catch (IOException e)
        {
          throw ((SecurityException)new SecurityException(e.getMessage()).initCause(e));
        }
      }
      SignerInfo[] infos = signedContent.getSignerInfos();
      for (int i = 0; i < infos.length; i++) {
        signedContent.checkValidity(infos[i]);
      }
    }
    
    public CertificateChain[] getChains()
    {
      SignerInfo[] infos = signedContent.getSignerInfos();
      CertificateChain[] chains = new CertificateChain[infos.length];
      for (int i = 0; i < chains.length; i++) {
        chains[i] = new LegacyVerifierFactory.LegacyChain(infos[i], signedContent);
      }
      return chains;
    }
    
    public boolean isSigned()
    {
      return signedContent.isSigned();
    }
    
    public String[] verifyContent()
    {
      List<String> invalidContent = new ArrayList(0);
      SignedContentEntry[] entries = signedContent.getSignedEntries();
      for (int i = 0; i < entries.length; i++) {
        try
        {
          entries[i].verify();
        }
        catch (InvalidContentException localInvalidContentException)
        {
          invalidContent.add(entries[i].getName());
        }
        catch (IOException localIOException)
        {
          invalidContent.add(entries[i].getName());
        }
      }
      return (String[])invalidContent.toArray(new String[invalidContent.size()]);
    }
  }
  
  static class LegacyChain
    implements CertificateChain
  {
    private final SignerInfo signerInfo;
    private final SignedContent content;
    
    public LegacyChain(SignerInfo signerInfo, SignedContent content)
    {
      this.signerInfo = signerInfo;
      this.content = content;
    }
    
    public Certificate[] getCertificates()
    {
      return signerInfo.getCertificateChain();
    }
    
    public String getChain()
    {
      StringBuffer sb = new StringBuffer();
      Certificate[] certs = getCertificates();
      for (int i = 0; i < certs.length; i++)
      {
        X509Certificate x509Cert = (X509Certificate)certs[i];
        sb.append(x509Cert.getSubjectDN().getName());
        sb.append("; ");
      }
      return sb.toString();
    }
    
    public Certificate getRoot()
    {
      Certificate[] certs = getCertificates();
      return certs.length > 0 ? certs[(certs.length - 1)] : null;
    }
    
    public Certificate getSigner()
    {
      Certificate[] certs = getCertificates();
      return certs.length > 0 ? certs[0] : null;
    }
    
    public Date getSigningTime()
    {
      return content.getSigningTime(signerInfo);
    }
    
    public boolean isTrusted()
    {
      return signerInfo.isTrusted();
    }
  }
}

/* Location:
 * Qualified Name:     org.eclipse.osgi.internal.signedcontent.LegacyVerifierFactory
 * Java Class Version: 1.4 (48.0)
 * JD-Core Version:    0.7.1
 */
package org.eclipse.osgi.internal.signedcontent;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class PKCS7DateParser
{
  static Date parseDate(PKCS7Processor pkcs7Processor, String signer, String file)
    throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, SignatureException, NoSuchProviderException
  {
    Map<int[], byte[]> unsignedAttrs = pkcs7Processor.getUnsignedAttrs();
    if (unsignedAttrs != null)
    {
      byte[] timeStampConstruct = retrieveTimeStampConstruct(unsignedAttrs);
      if (timeStampConstruct != null)
      {
        PKCS7Processor timestampProcess = new PKCS7Processor(timeStampConstruct, 0, timeStampConstruct.length, signer, file);
        timestampProcess.verifyCerts();
        pkcs7Processor.setTSACertificates(timestampProcess.getCertificates());
        return timestampProcess.getSigningTime();
      }
    }
    return null;
  }
  
  private static byte[] retrieveTimeStampConstruct(Map<int[], byte[]> unsignedAttrs)
  {
    Set<int[]> objIDs = unsignedAttrs.keySet();
    Iterator<int[]> iter = objIDs.iterator();
    while (iter.hasNext())
    {
      int[] objID = (int[])iter.next();
      if (Arrays.equals(SignedContentConstants.TIMESTAMP_OID, objID)) {
        return (byte[])unsignedAttrs.get(objID);
      }
    }
    return null;
  }
}

/* Location:
 * Qualified Name:     org.eclipse.osgi.internal.signedcontent.PKCS7DateParser
 * Java Class Version: 1.4 (48.0)
 * JD-Core Version:    0.7.1
 */
package org.eclipse.osgi.internal.signedcontent;

import java.io.ByteArrayInputStream;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Principal;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import javax.security.auth.x500.X500Principal;
import org.eclipse.osgi.util.NLS;

public class PKCS7Processor
  implements SignedContentConstants
{
  static CertificateFactory certFact;
  private final String signer;
  private final String file;
  private Certificate[] certificates;
  private Certificate[] tsaCertificates;
  private Map<int[], byte[]> signedAttrs;
  private Map<int[], byte[]> unsignedAttrs;
  private byte[] signature;
  private String digestAlgorithm;
  private String signatureAlgorithm;
  private Certificate signerCert;
  private Date signingTime;
  
  static
  {
    try
    {
      certFact = CertificateFactory.getInstance("X.509");
    }
    catch (CertificateException e)
    {
      SignedBundleHook.log(e.getMessage(), 4, e);
    }
  }
  
  private static String oid2String(int[] oid)
  {
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < oid.length; i++)
    {
      if (i > 0) {
        sb.append('.');
      }
      sb.append(oid[i]);
    }
    return sb.toString();
  }
  
  private static String findEncryption(int[] encOid)
    throws NoSuchAlgorithmException
  {
    if (Arrays.equals(DSA_OID, encOid)) {
      return "DSA";
    }
    if (Arrays.equals(RSA_OID, encOid)) {
      return "RSA";
    }
    throw new NoSuchAlgorithmException("No algorithm found for " + oid2String(encOid));
  }
  
  private static String findDigest(int[] digestOid)
    throws NoSuchAlgorithmException
  {
    if (Arrays.equals(SHA1_OID, digestOid)) {
      return "SHA1";
    }
    if (Arrays.equals(SHA224_OID, digestOid)) {
      return "SHA224";
    }
    if (Arrays.equals(SHA256_OID, digestOid)) {
      return "SHA256";
    }
    if (Arrays.equals(SHA384_OID, digestOid)) {
      return "SHA384";
    }
    if (Arrays.equals(SHA512_OID, digestOid)) {
      return "SHA512";
    }
    if (Arrays.equals(SHA512_224_OID, digestOid)) {
      return "SHA512-224";
    }
    if (Arrays.equals(SHA512_256_OID, digestOid)) {
      return "SHA512-256";
    }
    if (Arrays.equals(MD5_OID, digestOid)) {
      return "MD5";
    }
    if (Arrays.equals(MD2_OID, digestOid)) {
      return "MD2";
    }
    throw new NoSuchAlgorithmException("No algorithm found for " + oid2String(digestOid));
  }
  
  public PKCS7Processor(byte[] pkcs7, int pkcs7Offset, int pkcs7Length, String signer, String file)
    throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, SignatureException, NoSuchProviderException
  {
    this.signer = signer;
    this.file = file;
    
    List<Certificate> certs = null;
    
    BERProcessor bp = new BERProcessor(pkcs7, pkcs7Offset, pkcs7Length);
    
    bp = bp.stepInto();
    if (!Arrays.equals(bp.getObjId(), SIGNEDDATA_OID)) {
      throw new SignatureException(NLS.bind(SignedContentMessages.PKCS7_Invalid_File, signer, file));
    }
    bp.stepOver();
    bp = bp.stepInto();
    bp = bp.stepInto();
    bp.stepOver();
    bp.stepOver();
    
    processEncapContentInfo(bp);
    
    bp.stepOver();
    if ((classOfTag == 2) && (tag == 0)) {
      certs = processCertificates(bp);
    }
    if ((certs == null) || (certs.size() < 1)) {
      throw new SignatureException("There are no certificates in the .RSA/.DSA file!");
    }
    bp.stepOver();
    if ((classOfTag == 0) && (tag == 1)) {
      bp.stepOver();
    }
    processSignerInfos(bp, certs);
    
    certs = constructCertPath(certs, signerCert);
    
    certificates = ((Certificate[])certs.toArray(new Certificate[certs.size()]));
    verifyCerts();
    if (signingTime == null) {
      signingTime = PKCS7DateParser.parseDate(this, signer, file);
    }
  }
  
  private void processEncapContentInfo(BERProcessor bp)
    throws SignatureException
  {
    BERProcessor encapContentBERS = bp.stepInto();
    if (Arrays.equals(encapContentBERS.getObjId(), TIMESTAMP_TST_OID))
    {
      encapContentBERS.stepOver();
      BERProcessor encapContentBERS1 = encapContentBERS.stepInto();
      
      byte[] bytesman = encapContentBERS1.getBytes();
      BERProcessor eContentStructure = new BERProcessor(bytesman, 0, bytesman.length);
      
      BERProcessor eContentBER = eContentStructure.stepInto();
      int tsaVersion = eContentBER.getIntValue().intValue();
      if (tsaVersion != 1) {
        throw new SignatureException("Not a version 1 time-stamp token");
      }
      eContentBER.stepOver();
      
      eContentBER.stepOver();
      
      eContentBER.stepOver();
      
      eContentBER.stepOver();
      
      String dateString = new String(eContentBER.getBytes());
      if (!dateString.endsWith("Z")) {
        throw new SignatureException("Wrong dateformat used in time-stamp token");
      }
      int dotIndex = dateString.indexOf('.');
      StringBuffer dateFormatSB = new StringBuffer("yyyyMMddHHmmss");
      if (dotIndex != -1)
      {
        int noS = dateString.indexOf('Z') - 1 - dotIndex;
        dateFormatSB.append('.');
        for (int i = 0; i < noS; i++) {
          dateFormatSB.append('s');
        }
      }
      dateFormatSB.append("'Z'");
      try
      {
        DateFormat dateFormt = new SimpleDateFormat(dateFormatSB.toString(), Locale.ENGLISH);
        dateFormt.setTimeZone(TimeZone.getTimeZone("GMT"));
        signingTime = dateFormt.parse(dateString);
      }
      catch (ParseException e)
      {
        throw ((SignatureException)new SignatureException(SignedContentMessages.PKCS7_Parse_Signing_Time).initCause(e));
      }
    }
  }
  
  private List<Certificate> constructCertPath(List<Certificate> certs, Certificate targetCert)
  {
    List<Certificate> certsList = new ArrayList();
    certsList.add(targetCert);
    
    X509Certificate currentCert = (X509Certificate)targetCert;
    int numIteration = certs.size();
    int i = 0;
    while (i < numIteration)
    {
      X500Principal subject = currentCert.getSubjectX500Principal();
      X500Principal issuer = currentCert.getIssuerX500Principal();
      if (subject.equals(issuer)) {
        break;
      }
      currentCert = null;
      Iterator<Certificate> itr = certs.iterator();
      while (itr.hasNext())
      {
        X509Certificate tempCert = (X509Certificate)itr.next();
        if (tempCert.getSubjectX500Principal().equals(issuer))
        {
          certsList.add(tempCert);
          currentCert = tempCert;
        }
      }
      i++;
    }
    return certsList;
  }
  
  public void verifyCerts()
    throws InvalidKeyException, SignatureException, CertificateException, NoSuchAlgorithmException, NoSuchProviderException
  {
    if ((certificates == null) || (certificates.length == 0)) {
      throw new CertificateException("There are no certificates in the signature block file!");
    }
    int len = certificates.length;
    for (int i = 0; i < len; i++)
    {
      X509Certificate currentX509Cert = (X509Certificate)certificates[i];
      if (i == len - 1)
      {
        if (currentX509Cert.getSubjectDN().equals(currentX509Cert.getIssuerDN())) {
          currentX509Cert.verify(currentX509Cert.getPublicKey());
        }
      }
      else
      {
        X509Certificate nextX509Cert = (X509Certificate)certificates[(i + 1)];
        currentX509Cert.verify(nextX509Cert.getPublicKey());
      }
    }
  }
  
  private Certificate processSignerInfos(BERProcessor bp, List<Certificate> certs)
    throws CertificateException, NoSuchAlgorithmException, SignatureException
  {
    bp = bp.stepInto();
    bp = bp.stepInto();
    
    BigInteger signerInfoVersion = bp.getIntValue();
    if (signerInfoVersion.intValue() != 1) {
      throw new CertificateException(SignedContentMessages.PKCS7_SignerInfo_Version_Not_Supported);
    }
    bp.stepOver();
    
    BERProcessor issuerAndSN = bp.stepInto();
    X500Principal signerIssuer = new X500Principal(new ByteArrayInputStream(buffer, offset, endOffset - offset));
    issuerAndSN.stepOver();
    BigInteger sn = issuerAndSN.getIntValue();
    
    Certificate newSignerCert = null;
    
    Iterator<Certificate> itr = certs.iterator();
    while (itr.hasNext())
    {
      X509Certificate cert = (X509Certificate)itr.next();
      if ((cert.getIssuerX500Principal().equals(signerIssuer)) && (cert.getSerialNumber().equals(sn)))
      {
        newSignerCert = cert;
        break;
      }
    }
    if (newSignerCert == null) {
      throw new CertificateException("Signer certificate not in pkcs7block");
    }
    signerCert = newSignerCert;
    
    bp.stepOver();
    
    BERProcessor digestAlg = bp.stepInto();
    digestAlgorithm = findDigest(digestAlg.getObjId());
    
    bp.stepOver();
    
    processSignedAttributes(bp);
    
    BERProcessor encryptionAlg = bp.stepInto();
    signatureAlgorithm = findEncryption(encryptionAlg.getObjId());
    bp.stepOver();
    
    signature = bp.getBytes();
    
    bp.stepOver();
    
    processUnsignedAttributes(bp);
    
    return newSignerCert;
  }
  
  private void processUnsignedAttributes(BERProcessor bp)
    throws SignatureException
  {
    if ((classOfTag == 2) && (tag == 1))
    {
      unsignedAttrs = new HashMap();
      
      BERProcessor unsignedAttrsBERS = bp.stepInto();
      do
      {
        BERProcessor unsignedAttrBER = unsignedAttrsBERS.stepInto();
        
        int[] objID = unsignedAttrBER.getObjId();
        
        unsignedAttrBER.stepOver();
        byte[] structure = unsignedAttrBER.getBytes();
        unsignedAttrs.put(objID, structure);
        unsignedAttrsBERS.stepOver();
      } while (!unsignedAttrsBERS.endOfSequence());
    }
  }
  
  private void processSignedAttributes(BERProcessor bp)
    throws SignatureException
  {
    if (classOfTag == 2)
    {
      signedAttrs = new HashMap();
      
      BERProcessor signedAttrsBERS = bp.stepInto();
      do
      {
        BERProcessor signedAttrBER = signedAttrsBERS.stepInto();
        int[] signedAttrObjID = signedAttrBER.getObjId();
        
        signedAttrBER.stepOver();
        
        byte[] signedAttrStructure = signedAttrBER.getBytes();
        
        signedAttrs.put(signedAttrObjID, signedAttrStructure);
        
        signedAttrsBERS.stepOver();
      } while (!signedAttrsBERS.endOfSequence());
      bp.stepOver();
    }
  }
  
  public Certificate[] getCertificates()
  {
    return certificates == null ? new Certificate[0] : certificates;
  }
  
  public void verifySFSignature(byte[] data, int dataOffset, int dataLength)
    throws InvalidKeyException, NoSuchAlgorithmException, SignatureException
  {
    Signature sig = Signature.getInstance(digestAlgorithm + "with" + signatureAlgorithm);
    sig.initVerify(signerCert.getPublicKey());
    sig.update(data, dataOffset, dataLength);
    if (!sig.verify(signature)) {
      throw new SignatureException(NLS.bind(SignedContentMessages.Signature_Not_Verify, signer, file));
    }
  }
  
  public Map<int[], byte[]> getUnsignedAttrs()
  {
    return unsignedAttrs;
  }
  
  public Map<int[], byte[]> getSignedAttrs()
  {
    return signedAttrs;
  }
  
  private List<Certificate> processCertificates(BERProcessor bp)
    throws CertificateException, SignatureException
  {
    List<Certificate> rtvList = new ArrayList(3);
    
    BERProcessor certsBERS = bp.stepInto();
    do
    {
      X509Certificate x509Cert = (X509Certificate)certFact.generateCertificate(new ByteArrayInputStream(buffer, offset, endOffset - offset));
      if (x509Cert != null) {
        rtvList.add(x509Cert);
      }
      certsBERS.stepOver();
    } while (!certsBERS.endOfSequence());
    return rtvList;
  }
  
  public Date getSigningTime()
  {
    return signingTime;
  }
  
  void setTSACertificates(Certificate[] tsaCertificates)
  {
    this.tsaCertificates = tsaCertificates;
  }
  
  public Certificate[] getTSACertificates()
  {
    return tsaCertificates == null ? new Certificate[0] : tsaCertificates;
  }
}

/* Location:
 * Qualified Name:     org.eclipse.osgi.internal.signedcontent.PKCS7Processor
 * Java Class Version: 1.4 (48.0)
 * JD-Core Version:    0.7.1
 */
package org.eclipse.osgi.internal.signedcontent;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
import org.eclipse.osgi.signedcontent.SignerInfo;
import org.eclipse.osgi.util.NLS;

public class SignatureBlockProcessor
  implements SignedContentConstants
{
  private final SignedBundleFile signedBundle;
  private List<SignerInfo> signerInfos = new ArrayList();
  private Map<String, Object> contentMDResults = new HashMap();
  private Map<SignerInfo, Object[]> tsaSignerInfos;
  private final int supportFlags;
  
  public SignatureBlockProcessor(SignedBundleFile signedContent, int supportFlags)
  {
    signedBundle = signedContent;
    this.supportFlags = supportFlags;
  }
  
  public SignedContentImpl process()
    throws IOException, InvalidKeyException, SignatureException, CertificateException, NoSuchAlgorithmException, NoSuchProviderException
  {
    BundleFile wrappedBundleFile = signedBundle.getWrappedBundleFile();
    BundleEntry be = wrappedBundleFile.getEntry("META-INF/MANIFEST.MF");
    if (be == null) {
      return createUnsignedContent();
    }
    Enumeration<String> en = wrappedBundleFile.getEntryPaths("META-INF/");
    List<String> signers = new ArrayList(2);
    while (en.hasMoreElements())
    {
      String name = (String)en.nextElement();
      if (((name.endsWith(".DSA")) || (name.endsWith(".RSA"))) && (name.indexOf('/') == name.lastIndexOf('/'))) {
        signers.add(name);
      }
    }
    if (signers.size() == 0) {
      return createUnsignedContent();
    }
    byte[] manifestBytes = readIntoArray(be);
    for (Iterator<String> iSigners = signers.iterator(); iSigners.hasNext();) {
      processSigner(wrappedBundleFile, manifestBytes, (String)iSigners.next());
    }
    SignerInfo[] allSigners = (SignerInfo[])signerInfos.toArray(new SignerInfo[signerInfos.size()]);
    for (Iterator<Map.Entry<String, Object>> iResults = contentMDResults.entrySet().iterator(); iResults.hasNext();)
    {
      Map.Entry<String, Object> entry = (Map.Entry)iResults.next();
      
      List[] value = (List[])entry.getValue();
      SignerInfo[] entrySigners = (SignerInfo[])value[0].toArray(new SignerInfo[value[0].size()]);
      byte[][] entryResults = (byte[][])value[1].toArray(new byte[value[1].size()][]);
      entry.setValue(new Object[] { entrySigners, entryResults });
    }
    SignedContentImpl result = new SignedContentImpl(allSigners, (supportFlags & 0x4) != 0 ? contentMDResults : null);
    result.setContent(signedBundle);
    result.setTSASignerInfos(tsaSignerInfos);
    return result;
  }
  
  private SignedContentImpl createUnsignedContent()
  {
    SignedContentImpl result = new SignedContentImpl(new SignerInfo[0], contentMDResults);
    result.setContent(signedBundle);
    return result;
  }
  
  private void processSigner(BundleFile bf, byte[] manifestBytes, String signer)
    throws IOException, SignatureException, InvalidKeyException, CertificateException, NoSuchAlgorithmException, NoSuchProviderException
  {
    BundleEntry be = bf.getEntry(signer);
    byte[] pkcs7Bytes = readIntoArray(be);
    int dotIndex = signer.lastIndexOf('.');
    be = bf.getEntry(signer.substring(0, dotIndex) + ".SF");
    byte[] sfBytes = readIntoArray(be);
    
    String baseFile = bf.getBaseFile() != null ? bf.getBaseFile().toString() : null;
    PKCS7Processor processor = new PKCS7Processor(pkcs7Bytes, 0, pkcs7Bytes.length, signer, baseFile);
    
    processor.verifySFSignature(sfBytes, 0, sfBytes.length);
    
    String digAlg = getDigAlgFromSF(sfBytes);
    if (digAlg == null) {
      throw new SignatureException(NLS.bind(SignedContentMessages.SF_File_Parsing_Error, new String[] { bf.toString() }));
    }
    verifyManifestAndSignatureFile(manifestBytes, sfBytes);
    
    SignerInfoImpl signerInfo = new SignerInfoImpl(processor.getCertificates(), null, digAlg);
    if ((supportFlags & 0x4) != 0) {
      populateMDResults(manifestBytes, signerInfo);
    }
    signerInfos.add(signerInfo);
    
    Certificate[] tsaCerts = processor.getTSACertificates();
    Date signingTime = processor.getSigningTime();
    if ((tsaCerts != null) && (signingTime != null))
    {
      SignerInfoImpl tsaSignerInfo = new SignerInfoImpl(tsaCerts, null, digAlg);
      if (tsaSignerInfos == null) {
        tsaSignerInfos = new HashMap(2);
      }
      tsaSignerInfos.put(signerInfo, new Object[] { tsaSignerInfo, signingTime });
    }
  }
  
  private void verifyManifestAndSignatureFile(byte[] manifestBytes, byte[] sfBytes)
    throws SignatureException
  {
    String sf = new String(sfBytes);
    sf = stripContinuations(sf);
    
    int off = sf.indexOf("-Digest-Manifest: ");
    if (off != -1)
    {
      int start = sf.lastIndexOf('\n', off);
      String manifestDigest = null;
      if (start != -1)
      {
        String digestName = sf.substring(start + 1, off);
        if (digestName.equalsIgnoreCase("MD5")) {
          manifestDigest = calculateDigest(getMessageDigest("MD5"), manifestBytes);
        } else if (digestName.equalsIgnoreCase("SHA1")) {
          manifestDigest = calculateDigest(getMessageDigest("SHA1"), manifestBytes);
        } else {
          manifestDigest = calculateDigest(getMessageDigest(digestName), manifestBytes);
        }
        off += digestManifestSearchLen;
        
        int nIndex = sf.indexOf('\n', off);
        String digestValue = sf.substring(off, nIndex - 1);
        if (!digestValue.equals(manifestDigest))
        {
          SignatureException se = new SignatureException(NLS.bind(SignedContentMessages.Security_File_Is_Tampered, new String[] { signedBundle.getBaseFile().toString() }));
          SignedBundleHook.log(se.getMessage(), 4, se);
          throw se;
        }
      }
    }
  }
  
  private void populateMDResults(byte[] mfBuf, SignerInfo signerInfo)
    throws NoSuchAlgorithmException
  {
    String mfStr = new String(mfBuf);
    
    int entryStartOffset = mfStr.indexOf("\nName: ");
    int length = mfStr.length();
    while ((entryStartOffset != -1) && (entryStartOffset < length))
    {
      int entryEndOffset = mfStr.indexOf("\nName: ", entryStartOffset + 1);
      if (entryEndOffset == -1) {
        entryEndOffset = mfStr.length();
      }
      String entryStr = mfStr.substring(entryStartOffset + 1, entryEndOffset);
      entryStr = stripContinuations(entryStr);
      
      String entryName = getEntryFileName(entryStr);
      if (entryName != null)
      {
        String aDigestLine = getDigestLine(entryStr, signerInfo.getMessageDigestAlgorithm());
        if (aDigestLine != null)
        {
          String msgDigestAlgorithm = getDigestAlgorithmFromString(aDigestLine);
          if (!msgDigestAlgorithm.equalsIgnoreCase(signerInfo.getMessageDigestAlgorithm())) {
            continue;
          }
          byte[] digestResult = getDigestResultsList(aDigestLine);
          
          List[] mdResult = (List[])contentMDResults.get(entryName);
          if (mdResult == null)
          {
            List[] arrayLists = new ArrayList[2];
            mdResult = arrayLists;
            mdResult[0] = new ArrayList();
            mdResult[1] = new ArrayList();
            contentMDResults.put(entryName, mdResult);
          }
          mdResult[0].add(signerInfo);
          mdResult[1].add(digestResult);
        }
      }
      entryStartOffset = entryEndOffset;
    }
  }
  
  private static byte[] getDigestResultsList(String digestLines)
  {
    byte[] resultsList = null;
    if (digestLines != null)
    {
      String sDigestLine = digestLines;
      int indexDigest = sDigestLine.indexOf("-Digest: ");
      indexDigest += "-Digest: ".length();
      if (indexDigest >= sDigestLine.length()) {
        resultsList = null;
      }
      String sResult = sDigestLine.substring(indexDigest);
      try
      {
        resultsList = Base64.decode(sResult.getBytes());
      }
      catch (Throwable localThrowable)
      {
        resultsList = null;
      }
    }
    return resultsList;
  }
  
  private static String getDigestAlgorithmFromString(String digestLines)
    throws NoSuchAlgorithmException
  {
    if (digestLines != null)
    {
      int indexDigest = digestLines.indexOf("-Digest: ");
      String sDigestAlgType = digestLines.substring(0, indexDigest);
      if (sDigestAlgType.equalsIgnoreCase("MD5")) {
        return "MD5";
      }
      if (sDigestAlgType.equalsIgnoreCase("SHA1")) {
        return "SHA1";
      }
      return sDigestAlgType;
    }
    return null;
  }
  
  private static String getEntryFileName(String manifestEntry)
  {
    int nameStart = manifestEntry.indexOf("Name: ");
    if (nameStart == -1) {
      return null;
    }
    int nameEnd = manifestEntry.indexOf('\n', nameStart);
    if (nameEnd == -1) {
      return null;
    }
    if (manifestEntry.charAt(nameEnd - 1) == '\r') {
      nameEnd--;
    }
    nameStart += "Name: ".length();
    if (nameStart >= nameEnd) {
      return null;
    }
    return manifestEntry.substring(nameStart, nameEnd);
  }
  
  private static String calculateDigest(MessageDigest digest, byte[] bytes)
  {
    return new String(Base64.encode(digest.digest(bytes)));
  }
  
  static synchronized MessageDigest getMessageDigest(String algorithm)
  {
    try
    {
      return MessageDigest.getInstance(algorithm);
    }
    catch (NoSuchAlgorithmException e)
    {
      SignedBundleHook.log(e.getMessage(), 4, e);
    }
    return null;
  }
  
  private static String getDigAlgFromSF(byte[] SFBuf)
  {
    String mfStr = new String(SFBuf);
    String entryStr = null;
    
    int entryStartOffset = mfStr.indexOf("\nName: ");
    int length = mfStr.length();
    if ((entryStartOffset != -1) && (entryStartOffset < length))
    {
      int entryEndOffset = mfStr.indexOf("\nName: ", entryStartOffset + 1);
      if (entryEndOffset == -1) {
        entryEndOffset = mfStr.length();
      }
      entryStr = mfStr.substring(entryStartOffset + 1, entryEndOffset);
      entryStr = stripContinuations(entryStr);
    }
    if (entryStr != null)
    {
      String digestLine = getDigestLine(entryStr, null);
      
      return getMessageDigestName(digestLine);
    }
    return null;
  }
  
  private static String getDigestLine(String manifestEntry, String desireDigestAlg)
  {
    String result = null;
    
    int indexDigest = manifestEntry.indexOf("-Digest: ");
    if (indexDigest == -1) {
      return null;
    }
    while (indexDigest != -1)
    {
      int indexStart = manifestEntry.lastIndexOf('\n', indexDigest);
      if (indexStart == -1) {
        return null;
      }
      int indexEnd = manifestEntry.indexOf('\n', indexDigest);
      if (indexEnd == -1) {
        return null;
      }
      int indexEndToUse = indexEnd;
      if (manifestEntry.charAt(indexEndToUse - 1) == '\r') {
        indexEndToUse--;
      }
      int indexStartToUse = indexStart + 1;
      if (indexStartToUse >= indexEndToUse) {
        return null;
      }
      String digestLine = manifestEntry.substring(indexStartToUse, indexEndToUse);
      String digAlg = getMessageDigestName(digestLine);
      if ((desireDigestAlg != null) && 
        (desireDigestAlg.equalsIgnoreCase(digAlg))) {
        return digestLine;
      }
      result = digestLine;
      
      indexDigest = manifestEntry.indexOf("-Digest: ", indexEnd);
    }
    return result;
  }
  
  private static String getMessageDigestName(String digLine)
  {
    String rtvValue = null;
    if (digLine != null)
    {
      int indexDigest = digLine.indexOf("-Digest: ");
      if (indexDigest != -1) {
        rtvValue = digLine.substring(0, indexDigest);
      }
    }
    return rtvValue;
  }
  
  private static String stripContinuations(String entry)
  {
    if ((entry.indexOf("\n ") < 0) && (entry.indexOf("\r ") < 0)) {
      return entry;
    }
    StringBuffer buffer = new StringBuffer(entry);
    removeAll(buffer, "\r\n ");
    removeAll(buffer, "\n ");
    removeAll(buffer, "\r ");
    return buffer.toString();
  }
  
  private static StringBuffer removeAll(StringBuffer buffer, String toRemove)
  {
    int index = buffer.indexOf(toRemove);
    int length = toRemove.length();
    while (index > 0)
    {
      buffer.replace(index, index + length, "");
      index = buffer.indexOf(toRemove, index);
    }
    return buffer;
  }
  
  private static byte[] readIntoArray(BundleEntry be)
    throws IOException
  {
    int size = (int)be.getSize();
    InputStream is = be.getInputStream();
    try
    {
      byte[] b = new byte[size];
      int rc = readFully(is, b);
      if (rc != size) {
        throw new IOException("Couldn't read all of " + be.getName() + ": " + rc + " != " + size);
      }
      return b;
    }
    finally
    {
      try
      {
        is.close();
      }
      catch (IOException localIOException2) {}
    }
  }
  
  private static int readFully(InputStream is, byte[] b)
    throws IOException
  {
    int count = b.length;
    int offset = 0;
    int rc;
    while ((rc = is.read(b, offset, count)) > 0)
    {
      int rc;
      count -= rc;
      offset += rc;
    }
    return offset;
  }
}

/* Location:
 * Qualified Name:     org.eclipse.osgi.internal.signedcontent.SignatureBlockProcessor
 * Java Class Version: 1.4 (48.0)
 * JD-Core Version:    0.7.1
 */
package org.eclipse.osgi.internal.signedcontent;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;

class SignedBundleFile$SignedBundleEntry
  extends BundleEntry
{
  BundleEntry nestedEntry;
  final SignedBundleFile this$0;
  
  SignedBundleFile$SignedBundleEntry(SignedBundleFile paramSignedBundleFile, BundleEntry nestedEntry)
  {
    this.nestedEntry = nestedEntry;
  }
  
  public InputStream getInputStream()
    throws IOException
  {
    InputStream in = this$0.signedContent.getDigestInputStream(nestedEntry);
    if (in == null) {
      throw new SecurityException("Corrupted file: the digest does not exist for the file " + nestedEntry.getName());
    }
    return in;
  }
  
  public long getSize()
  {
    return nestedEntry.getSize();
  }
  
  public String getName()
  {
    return nestedEntry.getName();
  }
  
  public long getTime()
  {
    return nestedEntry.getTime();
  }
  
  public URL getLocalURL()
  {
    return nestedEntry.getLocalURL();
  }
  
  public URL getFileURL()
  {
    return nestedEntry.getFileURL();
  }
}

/* Location:
 * Qualified Name:     org.eclipse.osgi.internal.signedcontent.SignedBundleFile.SignedBundleEntry
 * Java Class Version: 1.4 (48.0)
 * JD-Core Version:    0.7.1
 */
package org.eclipse.osgi.internal.signedcontent;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.util.Date;
import java.util.Enumeration;
import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
import org.eclipse.osgi.service.security.TrustEngine;
import org.eclipse.osgi.signedcontent.SignedContent;
import org.eclipse.osgi.signedcontent.SignedContentEntry;
import org.eclipse.osgi.signedcontent.SignerInfo;
import org.eclipse.osgi.util.NLS;

public class SignedBundleFile
  extends BundleFile
  implements SignedContentConstants, SignedContent
{
  private BundleFile wrappedBundleFile;
  SignedContentImpl signedContent;
  private final int supportFlags;
  
  SignedBundleFile(SignedContentImpl signedContent, int supportFlags)
  {
    this.sig
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87

Further reading...

For more information on Java 1.5 Tiger, you may find Java 1.5 Tiger, A developer's Notebook by D. Flanagan and B. McLaughlin from O'Reilly of interest.

New!JAR listings


Copyright 2006-2019. Infinite Loop Ltd