0

My Android app is a MMORPG so it connects to my server. For some reason, this is breaking AdMob SSV. Ads show fine (test and real), but the server-side validation callback is never received. This is driving me insane - appreciate any help.

Here is the warning message I see in the logcat:

Precache exception
    hi: javax.net.ssl.SSLProtocolException: Read error: ssl=0x77c5e4c0b798: Failure in SSL library, usually a protocol error
    error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT (external/boringssl/src/crypto/fipsmodule/cipher/e_aes.c:1095 0x77c538ad22dc:0x00000000)
    error:1000008b:SSL routines:OPENSSL_internal:DECRYPTION_FAILED_OR_BAD_RECORD_MAC (external/boringssl/src/ssl/tls_record.cc:298 0x77c538ad22dc:0x00000000)
        at hd.a(:com.google.android.gms.policy_ads_fdr_dynamite@231710101@231710100057.526733554.526733554:6)
        at hq.a(:com.google.android.gms.policy_ads_fdr_dynamite@231710101@231710100057.526733554.526733554:0)
        at xv.b(:com.google.android.gms.policy_ads_fdr_dynamite@231710101@231710100057.526733554.526733554:2)
        at xv.a(:com.google.android.gms.policy_ads_fdr_dynamite@231710101@231710100057.526733554.526733554:2)
        at tx.t(:com.google.android.gms.policy_ads_fdr_dynamite@231710101@231710100057.526733554.526733554:4)
        at yr.a(:com.google.android.gms.policy_ads_fdr_dynamite@231710101@231710100057.526733554.526733554:0)
        at zt.m(:com.google.android.gms.policy_ads_fdr_dynamite@231710101@231710100057.526733554.526733554:2)
        at zt.l(:com.google.android.gms.policy_ads_fdr_dynamite@231710101@231710100057.526733554.526733554:31)
        at zt.j(:com.google.android.gms.policy_ads_fdr_dynamite@231710101@231710100057.526733554.526733554:39)
        at zt.d(:com.google.android.gms.policy_ads_fdr_dynamite@231710101@231710100057.526733554.526733554:30)
        at wc.run(:com.google.android.gms.policy_ads_fdr_dynamite@231710101@231710100057.526733554.526733554:43)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
        at java.lang.Thread.run(Thread.java:1012)
    Caused by: javax.net.ssl.SSLProtocolException: Read error: ssl=0x77c5e4c0b798: Failure in SSL library, usually a protocol error
    error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT (external/boringssl/src/crypto/fipsmodule/cipher/e_aes.c:1095 0x77c538ad22dc:0x00000000)
    error:1000008b:SSL routines:OPENSSL_internal:DECRYPTION_FAILED_OR_BAD_RECORD_MAC (external/boringssl/src/ssl/tls_record.cc:298 0x77c538ad22dc:0x00000000)
        at com.android.org.conscrypt.NativeCrypto.ENGINE_SSL_read_direct(Native Method)
        at com.android.org.conscrypt.NativeSsl.readDirectByteBuffer(NativeSsl.java:569)
        at com.android.org.conscrypt.ConscryptEngine.readPlaintextDataDirect(ConscryptEngine.java:1095)
        at com.android.org.conscrypt.ConscryptEngine.readPlaintextData(ConscryptEngine.java:1079)
        at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:876)
        at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:747)
        at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:712)
        at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.processDataFromSocket(ConscryptEngineSocket.java:858)
        at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.readUntilDataAvailable(ConscryptEngineSocket.java:824)
        at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.read(ConscryptEngineSocket.java:797)
        at com.android.okhttp.okio.Okio$2.read(Okio.java:138)
        at com.android.okhttp.okio.AsyncTimeout$2.read(AsyncTimeout.java:213)
        at com.android.okhttp.okio.RealBufferedSource.read(RealBufferedSource.java:51)
        at com.android.okhttp.internal.http.Http1xStream$FixedLengthSource.read(Http1xStream.java:395)
        at com.android.okhttp.okio.RealBufferedSource$1.read(RealBufferedSource.java:372)
        at hd.a(:com.google.android.gms.policy_ads_fdr_dynamite@231710101@231710100057.526733554.526733554:3)
        ... 13 more

Here is my client side SSL connection code:

//load your key store as a stream and initialize a KeyStore
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());

//if your store is password protected then declare it (it can be null however)
String tsName = "res/gamedata/truststore-bks";
char[] trustPassword = "REDACTED".toCharArray();

//load the stream to your store
trustStore.load(MyCommandReceiver.GetActiveActivity().getAssets().open(tsName), trustPassword);

//initialize a trust manager factory with the trusted store
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(trustStore);

//get the trust managers from the factory
TrustManager[] trustManagers = trustFactory.getTrustManagers();

//initialize an ssl context to use these managers and set as default
//SSLContext sslContext = SSLContext.getInstance("SSL");
SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
sslContext.init(null, trustManagers, null);
//SSLContext.setDefault(sslContext); //this was breaking admob ads from loading - and likely other stuff too

//create sslfactory from the ssl context
SSLSocketFactory factory = sslContext.getSocketFactory();

final int connectTimeout = 6 * 1000; //6 seconds to connect
if (GameActivity.isPROD) {
    //https://stackoverflow.com/questions/5715751/ssl-socket-connect-timeout
    //GameActivity.sC = (SSLSocket) SSLSocketFactory.getDefault().createSocket(); //the way code wanted me to do it
    GameActivity.sC = (SSLSocket) factory.createSocket();
    GameActivity.sC.setSoTimeout(connectTimeout);
    GameActivity.sC.connect(new InetSocketAddress(GameActivity.PROD_IP, GameActivity.PROD_PORT), connectTimeout);
} else {
    GameActivity.ShowLongToast("===DEV SERVER===");
    //https://stackoverflow.com/questions/5715751/ssl-socket-connect-timeout
    //GameActivity.sC = (SSLSocket) SSLSocketFactory.getDefault().createSocket(); //the way code wanted me to do it
    GameActivity.sC = (SSLSocket) factory.createSocket();
    GameActivity.sC.setSoTimeout(connectTimeout);
    GameActivity.sC.connect(new InetSocketAddress(GameActivity.DEV_IP, GameActivity.PROD_PORT), connectTimeout);
}

//GameActivity.sC.setEnabledProtocols(new String[]{"SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"});
//GameActivity.sC.setEnabledProtocols(new String[]{"TLSv1.2", "TLSv1.3"});
GameActivity.sC.setEnabledProtocols(new String[]{"TLSv1.3"});
//even tried with line above commented out

GameActivity.LoggerWrite("i", TAG, "LoginActivity:connectToServer: ------SUPPORTED CIPHER SUITES------");
GameActivity.LoggerWrite("i", TAG, Arrays.toString(factory.getSupportedCipherSuites()));
GameActivity.LoggerWrite("i", TAG, "LoginActivity:connectToServer:------SOCKET INFO------");
printSocketInfo(GameActivity.sC);
GameActivity.sC.setSoTimeout(0);
GameActivity.LoggerWrite("i", TAG, "LoginActivity:connectToServer:------START HANDSHAKE------");
GameActivity.sC.startHandshake();

GameActivity.sC.addHandshakeCompletedListener(new HandshakeCompletedListener() {
    @Override
    public void handshakeCompleted(HandshakeCompletedEvent arg0) {
        GameActivity.LoggerWrite("i", TAG, "LoginActivity:connectToServer:------HANDSHAKE-COMPLETED-LISTENER - START------");
        GameActivity.LoggerWrite("i", TAG, "LoginActivity:connectToServer:Cipher suite: " + arg0.getCipherSuite());

        GameActivity.LoggerWrite("i", TAG, "LoginActivity:connectToServer:Local Principal: " + arg0.getLocalPrincipal());

        Certificate[] peerCertificates = null;
        try {
            peerCertificates = arg0.getPeerCertificates();
            for (Certificate s : peerCertificates) {
                GameActivity.LoggerWrite("i", TAG, "LoginActivity:connectToServer:Peer Certificate(public key): " + s.getPublicKey());
            }
        } catch (SSLPeerUnverifiedException e) {
            GameActivity.LoggerWrite("e", TAG, "LoginActivity:connectToServer:arg0.getPeerCertificates()" + e);
        }

        try {
            GameActivity.LoggerWrite("i", TAG, "LoginActivity:connectToServer:Peer Principal: " + arg0.getPeerPrincipal());
        } catch (SSLPeerUnverifiedException e) {
            GameActivity.LoggerWrite("e", TAG, "LoginActivity:connectToServer:arg0.getPeerPrincipal()" + e);
        }
        GameActivity.LoggerWrite("i", TAG, "LoginActivity:connectToServer:Session: " + arg0.getSession());
        GameActivity.LoggerWrite("i", TAG, "LoginActivity:connectToServer:Socket: " + arg0.getSocket());
        GameActivity.LoggerWrite("i", TAG, "LoginActivity:connectToServer:Source: " + arg0.getSource());
        GameActivity.LoggerWrite("i", TAG, "LoginActivity:connectToServer:------HANDSHAKE-COMPLETED-LISTENER - END------");

//                        connectedToServer = true; //so subsequent clicks to Login don't make new connections
    }
});

GameActivity.LoggerWrite("i", TAG, "LoginActivity:connectToServer:------START DataStreams - START------");
GameActivity.commandIn = new DataInputStream(GameActivity.sC.getInputStream()); //create input-stream for a command socket
GameActivity.commandOut = new DataOutputStream(GameActivity.sC.getOutputStream()); //create output-stream for a command socket
GameActivity.LoggerWrite("i", TAG, "LoginActivity:connectToServer:------START DataStreams - END------");

//creating a thread for receiving commands
MyCommandReceiver.GetActiveActivity().runOnUiThread(new Runnable() {
    @Override
    public void run() {
        GameActivity.commandReceiver = new MyCommandReceiver();
        GameActivity.commandReceiverThread = new Thread(null, GameActivity.commandReceiver, "commandReceiver-" + ""); //characterName
        GameActivity.commandReceiverThread.setDaemon(true);
        GameActivity.commandReceiverThread.start();
    }
});
KisnardOnline
  • 653
  • 4
  • 16
  • 42

0 Answers0