use of org.matrix.androidsdk.crypto.data.MXOlmInboundGroupSession2 in project matrix-android-sdk by matrix-org.
the class MXFileCryptoStore method close.
@Override
public void close() {
// release JNI objects
ArrayList<OlmSession> olmSessions = new ArrayList<>();
Collection<HashMap<String, OlmSession>> sessionValues = mOlmSessions.values();
for (HashMap<String, OlmSession> value : sessionValues) {
olmSessions.addAll(value.values());
}
for (OlmSession olmSession : olmSessions) {
olmSession.releaseSession();
}
mOlmSessions.clear();
ArrayList<MXOlmInboundGroupSession2> groupSessions = new ArrayList<>();
Collection<HashMap<String, MXOlmInboundGroupSession2>> groupSessionsValues = mInboundGroupSessions.values();
for (HashMap<String, MXOlmInboundGroupSession2> map : groupSessionsValues) {
groupSessions.addAll(map.values());
}
for (MXOlmInboundGroupSession2 groupSession : groupSessions) {
if (null != groupSession.mSession) {
groupSession.mSession.releaseSession();
}
}
mInboundGroupSessions.clear();
}
use of org.matrix.androidsdk.crypto.data.MXOlmInboundGroupSession2 in project matrix-android-sdk by matrix-org.
the class MXFileCryptoStore method removeInboundGroupSession.
@Override
public void removeInboundGroupSession(String sessionId, String senderKey) {
if (!mIsReady) {
Log.e(LOG_TAG, "## removeInboundGroupSession() : the store is not ready");
return;
}
if ((null != sessionId) && (null != senderKey)) {
synchronized (mInboundGroupSessionsLock) {
if (mInboundGroupSessions.containsKey(senderKey)) {
MXOlmInboundGroupSession2 session = mInboundGroupSessions.get(senderKey).get(sessionId);
if (null != session) {
mInboundGroupSessions.get(senderKey).remove(sessionId);
File senderKeyFolder = new File(mInboundGroupSessionsFolder, encodeFilename(session.mSenderKey));
if (senderKeyFolder.exists()) {
File inboundSessionFile = new File(senderKeyFolder, encodeFilename(sessionId));
if (!inboundSessionFile.delete()) {
Log.e(LOG_TAG, "## removeInboundGroupSession() : fail to remove the sessionid " + sessionId);
}
}
// release the memory
session.mSession.releaseSession();
}
}
}
}
}
use of org.matrix.androidsdk.crypto.data.MXOlmInboundGroupSession2 in project matrix-android-sdk by matrix-org.
the class MXFileCryptoStore method preloadCryptoData.
/**
* Preload the crypto data
*/
private void preloadCryptoData() {
Log.d(LOG_TAG, "## preloadCryptoData() starts");
long t0 = System.currentTimeMillis();
Object olmAccountAsVoid;
if (mAccountFileTmp.exists()) {
olmAccountAsVoid = loadObject(mAccountFileTmp, "preloadCryptoData - mAccountFile - tmp");
} else {
olmAccountAsVoid = loadObject(mAccountFile, "preloadCryptoData - mAccountFile");
}
if (null != olmAccountAsVoid) {
try {
mOlmAccount = (OlmAccount) olmAccountAsVoid;
} catch (Exception e) {
mIsCorrupted = true;
Log.e(LOG_TAG, "## preloadCryptoData() - invalid mAccountFile " + e.getMessage());
}
}
Log.d(LOG_TAG, "## preloadCryptoData() : load mOlmAccount in " + (System.currentTimeMillis() - t0) + " ms");
// previous store format
if (!mDevicesFolder.exists()) {
Object usersDevicesInfoMapAsVoid;
// if the tmp exists, it means that the latest file backup has been killed / stopped
if (mDevicesFileTmp.exists()) {
usersDevicesInfoMapAsVoid = loadObject(mDevicesFileTmp, "preloadCryptoData - mUsersDevicesInfoMap - tmp");
} else {
usersDevicesInfoMapAsVoid = loadObject(mDevicesFile, "preloadCryptoData - mUsersDevicesInfoMap");
}
if (null != usersDevicesInfoMapAsVoid) {
try {
MXUsersDevicesMap objectAsMap = (MXUsersDevicesMap) usersDevicesInfoMapAsVoid;
mUsersDevicesInfoMap = new MXUsersDevicesMap<>(objectAsMap.getMap());
} catch (Exception e) {
mIsCorrupted = true;
Log.e(LOG_TAG, "## preloadCryptoData() - invalid mUsersDevicesInfoMap " + e.getMessage());
}
} else {
mIsCorrupted = false;
}
mDevicesFolder.mkdirs();
if (null != mUsersDevicesInfoMap) {
HashMap<String, HashMap<String, MXDeviceInfo>> map = mUsersDevicesInfoMap.getMap();
Set<String> userIds = map.keySet();
for (String userId : userIds) {
storeObject(map.get(userId), mDevicesFolder, userId, "convert devices map of " + userId);
}
mDevicesFileTmp.delete();
mDevicesFile.delete();
}
} else {
// the user devices are loaded on demand
mUsersDevicesInfoMap = new MXUsersDevicesMap<>();
}
long t2 = System.currentTimeMillis();
int algoSize = 0;
Object algorithmsAsVoid;
if (mAlgorithmsFileTmp.exists()) {
algorithmsAsVoid = loadObject(mAlgorithmsFileTmp, "preloadCryptoData - mRoomsAlgorithms - tmp");
} else {
algorithmsAsVoid = loadObject(mAlgorithmsFile, "preloadCryptoData - mRoomsAlgorithms");
}
if (null != algorithmsAsVoid) {
try {
Map<String, String> algorithmsMap = (Map<String, String>) algorithmsAsVoid;
mRoomsAlgorithms = new HashMap<>(algorithmsMap);
algoSize = mRoomsAlgorithms.size();
} catch (Exception e) {
mIsCorrupted = true;
Log.e(LOG_TAG, "## preloadCryptoData() - invalid mAlgorithmsFile " + e.getMessage());
}
}
Log.d(LOG_TAG, "## preloadCryptoData() : load mRoomsAlgorithms (" + algoSize + " algos) in " + (System.currentTimeMillis() - t2) + " ms");
Object trackingStatusesAsVoid;
if (mTrackingStatusesFileTmp.exists()) {
trackingStatusesAsVoid = loadObject(mTrackingStatusesFileTmp, "preloadCryptoData - mTrackingStatuses - tmp");
} else {
trackingStatusesAsVoid = loadObject(mTrackingStatusesFile, "preloadCryptoData - mTrackingStatuses");
}
if (null != trackingStatusesAsVoid) {
try {
mTrackingStatuses = new HashMap<>((Map<String, Integer>) trackingStatusesAsVoid);
} catch (Exception e) {
Log.e(LOG_TAG, "## preloadCryptoData() - invalid mTrackingStatuses " + e.getMessage());
}
}
File outgoingRequestFile;
if (mOutgoingRoomKeyRequestsFileTmp.exists()) {
outgoingRequestFile = mOutgoingRoomKeyRequestsFileTmp;
} else {
outgoingRequestFile = mOutgoingRoomKeyRequestsFile;
}
if (outgoingRequestFile.exists()) {
Object requestsAsVoid = loadObject(outgoingRequestFile, "get outgoing key request");
try {
if (null != requestsAsVoid) {
mOutgoingRoomKeyRequests.putAll((Map<Map<String, String>, OutgoingRoomKeyRequest>) requestsAsVoid);
}
} catch (Exception e) {
Log.e(LOG_TAG, "## preloadCryptoData() : mOutgoingRoomKeyRequests init failed " + e.getMessage());
}
}
if (mOlmSessionsFolder.exists()) {
long t3 = System.currentTimeMillis();
mOlmSessions = new HashMap<>();
String[] olmSessionFiles = mOlmSessionsFolder.list();
if (null != olmSessionFiles) {
// build mOlmSessions for the file system
for (int i = 0; i < olmSessionFiles.length; i++) {
String deviceKey = olmSessionFiles[i];
HashMap<String, OlmSession> olmSessionSubMap = new HashMap<>();
File sessionsDeviceFolder = new File(mOlmSessionsFolder, deviceKey);
String[] sessionIds = sessionsDeviceFolder.list();
if (null != sessionIds) {
for (int j = 0; j < sessionIds.length; j++) {
String sessionId = sessionIds[j];
OlmSession olmSession = (OlmSession) loadObject(new File(sessionsDeviceFolder, sessionId), "load the olmSession " + deviceKey + " " + sessionId);
if (null != olmSession) {
olmSessionSubMap.put(decodeFilename(sessionId), olmSession);
}
}
}
mOlmSessions.put(decodeFilename(deviceKey), olmSessionSubMap);
}
Log.d(LOG_TAG, "## preloadCryptoData() : load " + olmSessionFiles.length + " olmsessions in " + (System.currentTimeMillis() - t3) + " ms");
}
} else {
Object olmSessionsAsVoid;
if (mOlmSessionsFileTmp.exists()) {
olmSessionsAsVoid = loadObject(mOlmSessionsFileTmp, "preloadCryptoData - mOlmSessions - tmp");
} else {
olmSessionsAsVoid = loadObject(mOlmSessionsFile, "preloadCryptoData - mOlmSessions");
}
if (null != olmSessionsAsVoid) {
try {
Map<String, Map<String, OlmSession>> olmSessionMap = (Map<String, Map<String, OlmSession>>) olmSessionsAsVoid;
mOlmSessions = new HashMap<>();
for (String key : olmSessionMap.keySet()) {
mOlmSessions.put(key, new HashMap<>(olmSessionMap.get(key)));
}
// convert to the new format
if (!mOlmSessionsFolder.mkdir()) {
Log.e(LOG_TAG, "Cannot create the folder " + mOlmSessionsFolder);
}
for (String key : olmSessionMap.keySet()) {
Map<String, OlmSession> submap = olmSessionMap.get(key);
File submapFolder = new File(mOlmSessionsFolder, encodeFilename(key));
if (!submapFolder.mkdir()) {
Log.e(LOG_TAG, "Cannot create the folder " + submapFolder);
}
for (String sessionId : submap.keySet()) {
storeObject(submap.get(sessionId), submapFolder, encodeFilename(sessionId), "Convert olmSession " + key + " " + sessionId);
}
}
} catch (Exception e) {
mIsCorrupted = true;
Log.e(LOG_TAG, "## preloadCryptoData() - invalid mSessionsFile " + e.getMessage());
}
mOlmSessionsFileTmp.delete();
mOlmSessionsFile.delete();
}
}
if (mInboundGroupSessionsFolder.exists()) {
long t4 = System.currentTimeMillis();
mInboundGroupSessions = new HashMap<>();
int count = 0;
String[] keysFolder = mInboundGroupSessionsFolder.list();
if (null != keysFolder) {
for (int i = 0; i < keysFolder.length; i++) {
File keyFolder = new File(mInboundGroupSessionsFolder, keysFolder[i]);
HashMap<String, MXOlmInboundGroupSession2> submap = new HashMap<>();
String[] sessionIds = keyFolder.list();
if (null != sessionIds) {
for (int j = 0; j < sessionIds.length; j++) {
File inboundSessionFile = new File(keyFolder, sessionIds[j]);
try {
Object inboundSessionAsVoid = loadObject(inboundSessionFile, "load inboundsession " + sessionIds[j] + " ");
MXOlmInboundGroupSession2 inboundSession;
if ((null != inboundSessionAsVoid) && (inboundSessionAsVoid instanceof MXOlmInboundGroupSession)) {
inboundSession = new MXOlmInboundGroupSession2((MXOlmInboundGroupSession) inboundSessionAsVoid);
} else {
inboundSession = (MXOlmInboundGroupSession2) inboundSessionAsVoid;
}
if (null != inboundSession) {
submap.put(decodeFilename(sessionIds[j]), inboundSession);
} else {
Log.e(LOG_TAG, "## preloadCryptoData() : delete " + inboundSessionFile);
inboundSessionFile.delete();
mIsCorrupted = false;
}
count++;
} catch (Exception e) {
Log.e(LOG_TAG, "## preloadCryptoData() - invalid mInboundGroupSessions " + e.getMessage());
}
}
}
mInboundGroupSessions.put(decodeFilename(keysFolder[i]), submap);
}
}
Log.d(LOG_TAG, "## preloadCryptoData() : load " + count + " inboundGroupSessions in " + (System.currentTimeMillis() - t4) + " ms");
} else {
Object inboundGroupSessionsAsVoid;
if (mInboundGroupSessionsFileTmp.exists()) {
inboundGroupSessionsAsVoid = loadObject(mInboundGroupSessionsFileTmp, "preloadCryptoData - mInboundGroupSessions - tmp");
} else {
inboundGroupSessionsAsVoid = loadObject(mInboundGroupSessionsFile, "preloadCryptoData - mInboundGroupSessions");
}
if (null != inboundGroupSessionsAsVoid) {
try {
Map<String, Map<String, MXOlmInboundGroupSession2>> inboundGroupSessionsMap = (Map<String, Map<String, MXOlmInboundGroupSession2>>) inboundGroupSessionsAsVoid;
mInboundGroupSessions = new HashMap<>();
for (String key : inboundGroupSessionsMap.keySet()) {
mInboundGroupSessions.put(key, new HashMap<>(inboundGroupSessionsMap.get(key)));
}
} catch (Exception e) {
mIsCorrupted = true;
Log.e(LOG_TAG, "## preloadCryptoData() - invalid mInboundGroupSessions " + e.getMessage());
}
if (!mInboundGroupSessionsFolder.mkdirs()) {
Log.e(LOG_TAG, "Cannot create the folder " + mInboundGroupSessionsFolder);
}
// convert to the new format
for (String key : mInboundGroupSessions.keySet()) {
File keyFolder = new File(mInboundGroupSessionsFolder, encodeFilename(key));
if (!keyFolder.mkdirs()) {
Log.e(LOG_TAG, "Cannot create the folder " + keyFolder);
}
Map<String, MXOlmInboundGroupSession2> inboundMaps = mInboundGroupSessions.get(key);
for (String sessionId : inboundMaps.keySet()) {
storeObject(inboundMaps.get(sessionId), keyFolder, encodeFilename(sessionId), "Convert inboundsession");
}
}
}
mInboundGroupSessionsFileTmp.delete();
mInboundGroupSessionsFile.delete();
}
if ((null == mOlmAccount) && (mUsersDevicesInfoMap.getMap().size() > 0)) {
mIsCorrupted = true;
Log.e(LOG_TAG, "## preloadCryptoData() - there is no account but some devices are defined");
}
}
use of org.matrix.androidsdk.crypto.data.MXOlmInboundGroupSession2 in project matrix-android-sdk by matrix-org.
the class MXOlmDevice method decryptGroupMessage.
/**
* Decrypt a received message with an inbound group session.
*
* @param body the base64-encoded body of the encrypted message.
* @param roomId theroom in which the message was received.
* @param timeline the id of the timeline where the event is decrypted. It is used to prevent replay attack.
* @param sessionId the session identifier.
* @param senderKey the base64-encoded curve25519 key of the sender.
* @return the decrypting result. Nil if the sessionId is unknown.
*/
public MXDecryptionResult decryptGroupMessage(String body, String roomId, String timeline, String sessionId, String senderKey) throws MXDecryptionException {
MXDecryptionResult result = new MXDecryptionResult();
MXOlmInboundGroupSession2 session = getInboundGroupSession(sessionId, senderKey, roomId);
if (null != session) {
// the HS pretending a message was targeting a different room.
if (TextUtils.equals(roomId, session.mRoomId)) {
String errorMessage = "";
OlmInboundGroupSession.DecryptMessageResult decryptResult = null;
try {
decryptResult = session.mSession.decryptMessage(body);
} catch (Exception e) {
Log.e(LOG_TAG, "## decryptGroupMessage () : decryptMessage failed " + e.getMessage());
errorMessage = e.getMessage();
}
if (null != decryptResult) {
if (null != timeline) {
if (!mInboundGroupSessionMessageIndexes.containsKey(timeline)) {
mInboundGroupSessionMessageIndexes.put(timeline, new HashMap<String, Boolean>());
}
String messageIndexKey = senderKey + "|" + sessionId + "|" + decryptResult.mIndex;
if (null != mInboundGroupSessionMessageIndexes.get(timeline).get(messageIndexKey)) {
String reason = String.format(MXCryptoError.DUPLICATE_MESSAGE_INDEX_REASON, decryptResult.mIndex);
Log.e(LOG_TAG, "## decryptGroupMessage() : " + reason);
throw new MXDecryptionException(new MXCryptoError(MXCryptoError.DUPLICATED_MESSAGE_INDEX_ERROR_CODE, MXCryptoError.UNABLE_TO_DECRYPT, reason));
}
mInboundGroupSessionMessageIndexes.get(timeline).put(messageIndexKey, true);
}
mStore.storeInboundGroupSession(session);
try {
JsonParser parser = new JsonParser();
result.mPayload = parser.parse(JsonUtils.convertFromUTF8(decryptResult.mDecryptedMessage));
} catch (Exception e) {
Log.e(LOG_TAG, "## decryptGroupMessage() : RLEncoder.encode failed " + e.getMessage());
return null;
}
if (null == result.mPayload) {
Log.e(LOG_TAG, "## decryptGroupMessage() : fails to parse the payload");
return null;
}
result.mKeysClaimed = session.mKeysClaimed;
result.mSenderKey = senderKey;
result.mForwardingCurve25519KeyChain = session.mForwardingCurve25519KeyChain;
} else {
Log.e(LOG_TAG, "## decryptGroupMessage() : failed to decode the message");
throw new MXDecryptionException(new MXCryptoError(MXCryptoError.OLM_ERROR_CODE, errorMessage, null));
}
} else {
String reason = String.format(MXCryptoError.INBOUND_SESSION_MISMATCH_ROOM_ID_REASON, roomId, session.mRoomId);
Log.e(LOG_TAG, "## decryptGroupMessage() : " + reason);
throw new MXDecryptionException(new MXCryptoError(MXCryptoError.INBOUND_SESSION_MISMATCH_ROOM_ID_ERROR_CODE, MXCryptoError.UNABLE_TO_DECRYPT, reason));
}
} else {
Log.e(LOG_TAG, "## decryptGroupMessage() : Cannot retrieve inbound group session " + sessionId);
throw new MXDecryptionException(mInboundGroupSessionWithIdError);
}
return result;
}
use of org.matrix.androidsdk.crypto.data.MXOlmInboundGroupSession2 in project matrix-android-sdk by matrix-org.
the class MXOlmDevice method getInboundGroupSession.
/**
* Extract an InboundGroupSession from the session store and do some check.
* mInboundGroupSessionWithIdError describes the failure reason.
*
* @param roomId the room where the sesion is used.
* @param sessionId the session identifier.
* @param senderKey the base64-encoded curve25519 key of the sender.
* @return the inbound group session.
*/
public MXOlmInboundGroupSession2 getInboundGroupSession(String sessionId, String senderKey, String roomId) {
mInboundGroupSessionWithIdError = null;
MXOlmInboundGroupSession2 session = mStore.getInboundGroupSession(sessionId, senderKey);
if (null != session) {
// the HS pretending a message was targeting a different room.
if (!TextUtils.equals(roomId, session.mRoomId)) {
String errorDescription = String.format(MXCryptoError.INBOUND_SESSION_MISMATCH_ROOM_ID_REASON, roomId, session.mRoomId);
Log.e(LOG_TAG, "## getInboundGroupSession() : " + errorDescription);
mInboundGroupSessionWithIdError = new MXCryptoError(MXCryptoError.INBOUND_SESSION_MISMATCH_ROOM_ID_ERROR_CODE, MXCryptoError.UNABLE_TO_DECRYPT, errorDescription);
}
} else {
Log.e(LOG_TAG, "## getInboundGroupSession() : Cannot retrieve inbound group session " + sessionId);
mInboundGroupSessionWithIdError = new MXCryptoError(MXCryptoError.UNKNOWN_INBOUND_SESSION_ID_ERROR_CODE, MXCryptoError.UNKNOWN_INBOUND_SESSION_ID_REASON, null);
}
return session;
}
Aggregations