FileDocCategorySizeDatePackage
VerifierImpl.javaAPI DocphoneME MR2 API (J2ME)11630Wed May 02 18:00:08 BST 2007com.sun.midp.installer

VerifierImpl

public class VerifierImpl extends Object implements Verifier
Verifier that is able to verify midlet suite's signature. It is used when the crypto code is present in the build.

Fields Summary
InstallState
state
Current installation state.
private String[]
authPath
Authorization Path: A list of authority names from the verification, begining with the most trusted.
private X509Certificate
cpCert
Authenticated content provider certificate.
Constructors Summary
public VerifierImpl(InstallState installState)
Constructor.

param
state current state of the installation

        state = installState;
    
Methods Summary
private intcheckCertChain(int chainNum)
Check to see if a provider certificate chain is issued by a known CA. Set the authPath field to names of the auth chain in any case. Authenticate the chain and set the cpCert field to the provider's certificate if the CA is known.

param
chainNum the number of the chain
return
1 if the CA of the chain is known, 0 if not, -1 if the chain is not found
exception
InvalidJadException if something other wrong with a other than an unknown CA

        int certNum;
        Vector derCerts = new Vector();
        String base64Cert;
        byte[] derCert;
        WebPublicKeyStore keyStore;
        Vector keys;
        PublicKeyInfo keyInfo;

        for (certNum = 1; ; certNum++) {
            base64Cert = state.getAppProperty(CERT_PROP +
                                              chainNum + "-" + certNum);
            if (base64Cert == null) {
                break;
            }

            try {
                derCert = Base64.decode(base64Cert);
                derCerts.addElement(X509Certificate.generateCertificate(
                    derCert, 0, derCert.length));
            } catch (Exception e) {
                throw new InvalidJadException(
                    InvalidJadException.CORRUPT_PROVIDER_CERT);
            }
        }

        if (certNum == 1) {
            // Chain not found
            return -1;
        }

        try {
            keyStore = WebPublicKeyStore.getTrustedKeyStore();
            authPath = X509Certificate.verifyChain(derCerts,
                            X509Certificate.DIGITAL_SIG_KEY_USAGE,
                            X509Certificate.CODE_SIGN_EXT_KEY_USAGE,
                            keyStore);
        } catch (CertificateException ce) {
            switch (ce.getReason()) {
            case CertificateException.UNRECOGNIZED_ISSUER:
                authPath = new String[1];
                authPath[0] = ce.getCertificate().getIssuer();

                // Issuer not found
                return 0;

            case CertificateException.EXPIRED:
            case CertificateException.NOT_YET_VALID:
                throw new InvalidJadException(
                    InvalidJadException.EXPIRED_PROVIDER_CERT,
                    ce.getCertificate().getSubject());

            case CertificateException.ROOT_CA_EXPIRED:
                throw new InvalidJadException(
                    InvalidJadException.EXPIRED_CA_KEY,
                    ce.getCertificate().getIssuer());
            }

            throw new InvalidJadException(
                InvalidJadException.INVALID_PROVIDER_CERT,
                ce.getCertificate().getSubject());
        }

        // The root CA may have been disabled for software authorization.
        keys = keyStore.findKeys(authPath[0]);
        keyInfo = (PublicKeyInfo)keys.elementAt(0);

        if (!keyInfo.isEnabled()) {
            throw new InvalidJadException(
                InvalidJadException.CA_DISABLED,
                authPath[0]);
        }

        cpCert = (X509Certificate)derCerts.elementAt(0);

        // Authenticated
        return 1;
    
private voidfindProviderCert()
Find the first provider certificate that is signed by a known CA. Set the lastCA field to name of the CA. Set the cpCert field to the provider certificate. IMPL_NOTE: in the case of erroneous certificate chains the first chain error will be thrown.

exception
InvalidJadException if the JAR is not valid or the provider certificate is missing or a general certificate error

        int chain;
        int result;
        InvalidJadException pendingException = null;

        for (chain = 1; ; chain++) {
            // sets the authPath and cpCert
            try {
                result = checkCertChain(chain);
            } catch (InvalidJadException ije) {
                // According to the spec, if some chain is invalid and
                // the next chain exists, it should also be verified;
                // the first valid chain should be used for the jar
                // verification.
                if (pendingException == null) {
                    pendingException = ije;
                }
                continue;
            }

            if (result == 1) {
                // we found the good chain
                return;
            }

            if (result == -1) {
                // chain not found, done
                break;
            }
        }

        if (pendingException != null) {
            throw pendingException;
        }

        if (chain == 1) {
            throw new
                InvalidJadException(InvalidJadException.MISSING_PROVIDER_CERT);
        }

        // None of the certificates were issued by a known CA
        throw new
            InvalidJadException(InvalidJadException.UNKNOWN_CA,
                                authPath[0]);
    
public java.lang.StringgetSecurityDomainName(java.lang.String ca)
Looks up the domain of a MIDlet suite.

param
ca CA of an installed suite
return
security domain of the MIDlet suite

        Vector keys;
        String domain;

        /*
         * look up the domain owner, then get the domain from the
         * trusted key store and set the security domain
         */
        try {
            keys = WebPublicKeyStore.getTrustedKeyStore().
                         findKeys(ca);

            domain = ((PublicKeyInfo)keys.elementAt(0)).getDomain();
        } catch (Exception e) {
            domain = Permissions.UNIDENTIFIED_DOMAIN_BINDING;
        }

        return domain;
    
public booleanisJadSigned()
Checks to see if the JAD has a signature, but does not verify the signature.

return
true if the JAD has a signature

        return state.getAppProperty(SIG_PROP) != null;
    
public java.lang.String[]verifyJar(com.sun.midp.io.j2me.storage.RandomAccessStream jarStorage, java.lang.String jarFilename)
Verifies a Jar. On success set the name of the domain owner in the install state. Post any error back to the server.

param
jarStorage System store for applications
param
jarFilename name of the jar to read.
exception
IOException if any error prevents the reading of the JAR
exception
InvalidJadException if the JAR is not valid or the provider certificate is missing

        InputStream jarStream;
        String jarSig;

        jarSig = state.getAppProperty(SIG_PROP);
        if (jarSig == null) {
            // no signature to verify
            return null;
        }

        authPath = null;

        // This will fill in the cpCert and authPath fields
        findProviderCert();

        jarStorage.connect(jarFilename, Connector.READ);

        try {
            jarStream = jarStorage.openInputStream();

            try {
                verifyStream(jarStream, jarSig);
                // state.installInfo.authPath = authPath;
            } finally {
                jarStream.close();
            }
        } finally {
            jarStorage.disconnect();
        }

        return authPath;
    
private voidverifyStream(java.io.InputStream stream, java.lang.String base64Signature)
Common routine that verifies a stream of bytes. The cpCert field must be set before calling.

param
stream stream to verify
param
base64Signature The base64 encoding of the PKCS v1.5 SHA with RSA signature of this stream.
exception
NullPointerException if the public keystore has not been established.
exception
InvalidJadException the JAR signature is not valid
exception
IOException if any error prevents the reading of the JAR

        PublicKey cpKey;
        byte[] sig;
        Signature sigVerifier;
        byte[] temp;
        int bytesRead;
        byte[] hash;

        try {
            cpKey = cpCert.getPublicKey();
        } catch (CertificateException e) {
            throw new
                InvalidJadException(InvalidJadException.INVALID_PROVIDER_CERT);
        }

        try {
            sig = Base64.decode(base64Signature);
        } catch (IOException e) {
            throw new
                InvalidJadException(InvalidJadException.CORRUPT_SIGNATURE);
        }

        try {
            // verify the jad signature
            sigVerifier = Signature.getInstance("SHA1withRSA");
            sigVerifier.initVerify(cpKey);

            temp = new byte[1024];
            for (; ; ) {
                bytesRead = stream.read(temp);
                if (bytesRead == -1) {
                    break;
                }

                sigVerifier.update(temp, 0, bytesRead);
            }

            if (!sigVerifier.verify(sig)) {
                throw new
                    InvalidJadException(InvalidJadException.INVALID_SIGNATURE);
            }
        } catch (GeneralSecurityException e) {
            throw new
                InvalidJadException(InvalidJadException.INVALID_SIGNATURE);
        }