save certificate when verifying with x509

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java     |  6 
src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java |  6 
src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java       | 31 
3 files changed, 39 insertions(+), 4 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java 🔗

@@ -597,8 +597,10 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
 							if (verifier.verify(verification.second)) {
 								try {
 									mXmppConnectionService.getMemorizingTrustManager().getNonInteractive().checkClientTrusted(verification.first, "RSA");
-									Log.d(Config.LOGTAG, "verified session with x.509 signature. fingerprint was: "+session.getFingerprint());
-									setFingerprintTrust(session.getFingerprint(), XmppAxolotlSession.Trust.TRUSTED_X509);
+									String fingerprint = session.getFingerprint();
+									Log.d(Config.LOGTAG, "verified session with x.509 signature. fingerprint was: "+fingerprint);
+									setFingerprintTrust(fingerprint, XmppAxolotlSession.Trust.TRUSTED_X509);
+									axolotlStore.setFingerprintCertificate(fingerprint, verification.first[0]);
 									fetchStatusMap.put(address, FetchStatus.SUCCESS_VERIFIED);
 									finishBuildingSessionsFromPEP(address);
 									return;

src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java 🔗

@@ -15,6 +15,7 @@ import org.whispersystems.libaxolotl.state.SessionRecord;
 import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
 import org.whispersystems.libaxolotl.util.KeyHelper;
 
+import java.security.cert.X509Certificate;
 import java.util.List;
 import java.util.Set;
 
@@ -36,6 +37,7 @@ public class SQLiteAxolotlStore implements AxolotlStore {
 	public static final String NAME = "name";
 	public static final String TRUSTED = "trusted";
 	public static final String OWN = "ownkey";
+	public static final String CERTIFICATE = "certificate";
 
 	public static final String JSONKEY_REGISTRATION_ID = "axolotl_reg_id";
 	public static final String JSONKEY_CURRENT_PREKEY_ID = "axolotl_cur_prekey_id";
@@ -213,6 +215,10 @@ public class SQLiteAxolotlStore implements AxolotlStore {
 		trustCache.remove(fingerprint);
 	}
 
+	public void setFingerprintCertificate(String fingerprint, X509Certificate x509Certificate) {
+		mXmppConnectionService.databaseBackend.setIdentityKeyCertificate(account, fingerprint, x509Certificate);
+	}
+
 	public Set<IdentityKey> getContactKeysWithTrust(String bareJid, XmppAxolotlSession.Trust trust) {
 		return mXmppConnectionService.databaseBackend.loadIdentityKeys(account, bareJid, trust);
 	}

src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java 🔗

@@ -15,11 +15,14 @@ import org.whispersystems.libaxolotl.AxolotlAddress;
 import org.whispersystems.libaxolotl.IdentityKey;
 import org.whispersystems.libaxolotl.IdentityKeyPair;
 import org.whispersystems.libaxolotl.InvalidKeyException;
+import org.whispersystems.libaxolotl.state.AxolotlStore;
 import org.whispersystems.libaxolotl.state.PreKeyRecord;
 import org.whispersystems.libaxolotl.state.SessionRecord;
 import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
 
 import java.io.IOException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -44,7 +47,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
 	private static DatabaseBackend instance = null;
 
 	private static final String DATABASE_NAME = "history";
-	private static final int DATABASE_VERSION = 21;
+	private static final int DATABASE_VERSION = 22;
 
 	private static String CREATE_CONTATCS_STATEMENT = "create table "
 			+ Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, "
@@ -102,6 +105,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
 			+ SQLiteAxolotlStore.NAME + " TEXT, "
 			+ SQLiteAxolotlStore.OWN + " INTEGER, "
 			+ SQLiteAxolotlStore.FINGERPRINT + " TEXT, "
+			+ SQLiteAxolotlStore.CERTIFICATE + " BLOB, "
 			+ SQLiteAxolotlStore.TRUSTED + " INTEGER, "
 			+ SQLiteAxolotlStore.KEY + " TEXT, FOREIGN KEY("
 			+ SQLiteAxolotlStore.ACCOUNT
@@ -345,6 +349,10 @@ public class DatabaseBackend extends SQLiteOpenHelper {
 						+ "=?", new String[]{account.getUuid()});
 			}
 		}
+
+		if (oldVersion < 22 && newVersion >= 22) {
+			db.execSQL("ALTER TABLE " + SQLiteAxolotlStore.IDENTITIES_TABLENAME + " ADD COLUMN " + SQLiteAxolotlStore.CERTIFICATE);
+		}
 	}
 
 	public static synchronized DatabaseBackend getInstance(Context context) {
@@ -596,7 +604,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
 		SQLiteDatabase db = this.getReadableDatabase();
 		String sql = "select messages.timeSent,messages.serverMsgId from accounts join conversations on accounts.uuid=conversations.accountUuid join messages on conversations.uuid=messages.conversationUuid where accounts.uuid=? and (messages.status=0 or messages.carbon=1 or messages.serverMsgId not null) order by messages.timesent desc limit 1";
 		String[] args = {account.getUuid()};
-		Cursor cursor = db.rawQuery(sql,args);
+		Cursor cursor = db.rawQuery(sql, args);
 		if (cursor.getCount() ==0) {
 			return null;
 		} else {
@@ -1050,6 +1058,25 @@ public class DatabaseBackend extends SQLiteOpenHelper {
 		return rows == 1;
 	}
 
+	public boolean setIdentityKeyCertificate(Account account, String fingerprint, X509Certificate x509Certificate) {
+		SQLiteDatabase db = this.getWritableDatabase();
+		String[] selectionArgs = {
+				account.getUuid(),
+				fingerprint
+		};
+		try {
+			ContentValues values = new ContentValues();
+			values.put(SQLiteAxolotlStore.CERTIFICATE, x509Certificate.getEncoded());
+			return db.update(SQLiteAxolotlStore.IDENTITIES_TABLENAME, values,
+					SQLiteAxolotlStore.ACCOUNT + " = ? AND "
+							+ SQLiteAxolotlStore.FINGERPRINT + " = ? ",
+					selectionArgs) == 1;
+		} catch (CertificateEncodingException e) {
+			Log.d(Config.LOGTAG,"could not encode certificate");
+			return false;
+		}
+	}
+
 	public void storeIdentityKey(Account account, String name, IdentityKey identityKey) {
 		storeIdentityKey(account, name, false, identityKey.getFingerprint().replaceAll("\\s", ""), Base64.encodeToString(identityKey.serialize(), Base64.DEFAULT));
 	}