001/** 002 * 003 * Copyright 2017 Paul Schaub 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.jivesoftware.smackx.omemo; 018 019import static org.jivesoftware.smackx.omemo.util.OmemoConstants.TARGET_PRE_KEY_COUNT; 020 021import java.util.Date; 022import java.util.HashMap; 023import java.util.Map; 024import java.util.WeakHashMap; 025import java.util.logging.Level; 026import java.util.logging.Logger; 027 028import org.jivesoftware.smack.roster.Roster; 029import org.jivesoftware.smack.roster.RosterEntry; 030 031import org.jivesoftware.smackx.omemo.element.OmemoBundleVAxolotlElement; 032import org.jivesoftware.smackx.omemo.element.OmemoDeviceListElement; 033import org.jivesoftware.smackx.omemo.exceptions.CannotEstablishOmemoSessionException; 034import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException; 035import org.jivesoftware.smackx.omemo.internal.CachedDeviceList; 036import org.jivesoftware.smackx.omemo.internal.OmemoDevice; 037import org.jivesoftware.smackx.omemo.internal.OmemoSession; 038import org.jivesoftware.smackx.omemo.util.OmemoKeyUtil; 039 040import org.jxmpp.jid.BareJid; 041 042/** 043 * Class that presents some methods that are used to load/generate/store keys and session data needed for OMEMO. 044 * 045 * @param <T_IdKeyPair> IdentityKeyPair class 046 * @param <T_IdKey> IdentityKey class 047 * @param <T_PreKey> PreKey class 048 * @param <T_SigPreKey> SignedPreKey class 049 * @param <T_Sess> Session class 050 * @param <T_Addr> Address class 051 * @param <T_ECPub> Elliptic Curve PublicKey class 052 * @param <T_Bundle> Bundle class 053 * @param <T_Ciph> Cipher class 054 * @author Paul Schaub 055 */ 056public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph> { 057 private static final Logger LOGGER = Logger.getLogger(OmemoStore.class.getName()); 058 059 private final WeakHashMap<OmemoManager, HashMap<OmemoDevice, OmemoSession<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph>>> 060 omemoSessions = new WeakHashMap<>(); 061 062 /** 063 * Create a new OmemoStore. 064 */ 065 public OmemoStore() { 066 067 } 068 069 /** 070 * Return true if this is a fresh installation. 071 * 072 * @param omemoManager omemoManager of our device. 073 * @return true or false. 074 */ 075 public abstract boolean isFreshInstallation(OmemoManager omemoManager); 076 077 /** 078 * Check, if our freshly generated deviceId is available (unique) in our deviceList. 079 * 080 * @param omemoManager omemoManager of our device. 081 * @param id our deviceId. 082 * @return true if list did not contain our id, else false 083 */ 084 boolean isAvailableDeviceId(OmemoManager omemoManager, int id) { 085 LOGGER.log(Level.INFO, "Check if id " + id + " is available..."); 086 087 // Lookup local cached device list 088 BareJid ownJid = omemoManager.getOwnJid(); 089 CachedDeviceList cachedDeviceList = loadCachedDeviceList(omemoManager, ownJid); 090 091 if (cachedDeviceList == null) { 092 cachedDeviceList = new CachedDeviceList(); 093 } 094 // Does the list already contain that id? 095 return !cachedDeviceList.contains(id); 096 } 097 098 /** 099 * Generate a new Identity (deviceId, identityKeys, preKeys...). 100 * 101 * @param omemoManager omemoManager of our device we want to regenerate. 102 * @throws CorruptedOmemoKeyException in case something goes wrong 103 */ 104 void regenerate(OmemoManager omemoManager) throws CorruptedOmemoKeyException { 105 LOGGER.log(Level.INFO, "Regenerating with deviceId " + omemoManager.getDeviceId() + "..."); 106 int nextPreKeyId = 1; 107 storeOmemoIdentityKeyPair(omemoManager, generateOmemoIdentityKeyPair()); 108 storeOmemoPreKeys(omemoManager, generateOmemoPreKeys(nextPreKeyId, TARGET_PRE_KEY_COUNT)); 109 storeLastPreKeyId(omemoManager, OmemoKeyUtil.addInBounds(nextPreKeyId, TARGET_PRE_KEY_COUNT)); 110 storeCurrentSignedPreKeyId(omemoManager, -1); //Set back to no-value default 111 changeSignedPreKey(omemoManager); 112 initializeOmemoSessions(omemoManager); 113 } 114 115 /** 116 * Merge the received OmemoDeviceListElement with the one we already have. If we had none, the received one is saved. 117 * 118 * @param omemoManager omemoManager of our device. 119 * @param contact Contact we received the list from. 120 * @param list List we received. 121 */ 122 void mergeCachedDeviceList(OmemoManager omemoManager, BareJid contact, OmemoDeviceListElement list) { 123 CachedDeviceList cached = loadCachedDeviceList(omemoManager, contact); 124 125 if (cached == null) { 126 cached = new CachedDeviceList(); 127 } 128 129 if (list != null) { 130 cached.merge(list.getDeviceIds()); 131 } 132 storeCachedDeviceList(omemoManager, contact, cached); 133 } 134 135 /** 136 * Renew our singed preKey. This should be done once every 7-14 days. 137 * The old signed PreKey should be kept for around a month or so (look it up in the XEP). 138 * 139 * @param omemoManager omemoManager of our device. 140 * @throws CorruptedOmemoKeyException when our identityKey is invalid 141 */ 142 void changeSignedPreKey(OmemoManager omemoManager) throws CorruptedOmemoKeyException { 143 int lastSignedPreKeyId = loadCurrentSignedPreKeyId(omemoManager); 144 if (lastSignedPreKeyId == -1) lastSignedPreKeyId = 0; 145 try { 146 T_SigPreKey newSignedPreKey = generateOmemoSignedPreKey(loadOmemoIdentityKeyPair(omemoManager), lastSignedPreKeyId + 1); 147 storeOmemoSignedPreKey(omemoManager, lastSignedPreKeyId + 1, newSignedPreKey); 148 storeCurrentSignedPreKeyId(omemoManager, lastSignedPreKeyId + 1); 149 setDateOfLastSignedPreKeyRenewal(omemoManager); 150 removeOldSignedPreKeys(omemoManager); 151 152 } catch (CorruptedOmemoKeyException e) { 153 LOGGER.log(Level.INFO, "Couldn't change SignedPreKey: " + e.getMessage()); 154 throw e; 155 } 156 } 157 158 /** 159 * Remove the oldest signedPreKey until there are only MAX_NUMBER_OF_STORED_SIGNED_PREKEYS left. 160 * 161 * @param omemoManager omemoManager of our device. 162 */ 163 private void removeOldSignedPreKeys(OmemoManager omemoManager) { 164 if (OmemoConfiguration.getMaxNumberOfStoredSignedPreKeys() <= 0) { 165 return; 166 } 167 168 int currentId = loadCurrentSignedPreKeyId(omemoManager); 169 if (currentId == -1) currentId = 0; 170 HashMap<Integer, T_SigPreKey> signedPreKeys = loadOmemoSignedPreKeys(omemoManager); 171 172 for (int i : signedPreKeys.keySet()) { 173 if (i <= currentId - OmemoConfiguration.getMaxNumberOfStoredSignedPreKeys()) { 174 LOGGER.log(Level.INFO, "Remove signedPreKey " + i + "."); 175 removeOmemoSignedPreKey(omemoManager, i); 176 } 177 } 178 } 179 180 /** 181 * Pack a OmemoBundleElement containing our key material. 182 * If we used up n preKeys since we last published our bundle, generate n new preKeys and add them to the bundle. 183 * We should always publish TARGET_PRE_KEY_COUNT keys. 184 * 185 * @param omemoManager omemoManager of our device. 186 * @return OmemoBundleElement 187 * @throws CorruptedOmemoKeyException when a key could not be loaded 188 */ 189 OmemoBundleVAxolotlElement packOmemoBundle(OmemoManager omemoManager) throws CorruptedOmemoKeyException { 190 int currentSignedPreKeyId = loadCurrentSignedPreKeyId(omemoManager); 191 if (currentSignedPreKeyId == -1) currentSignedPreKeyId = 0; 192 T_SigPreKey currentSignedPreKey = loadOmemoSignedPreKey(omemoManager, currentSignedPreKeyId); 193 T_IdKeyPair identityKeyPair = loadOmemoIdentityKeyPair(omemoManager); 194 195 HashMap<Integer, T_PreKey> preKeys = loadOmemoPreKeys(omemoManager); 196 int newKeysCount = TARGET_PRE_KEY_COUNT - preKeys.size(); 197 198 if (newKeysCount > 0) { 199 int lastPreKeyId = loadLastPreKeyId(omemoManager); 200 if (lastPreKeyId == -1) lastPreKeyId = 0; 201 HashMap<Integer, T_PreKey> newKeys = generateOmemoPreKeys(lastPreKeyId + 1, newKeysCount); 202 storeOmemoPreKeys(omemoManager, newKeys); 203 preKeys.putAll(newKeys); 204 storeLastPreKeyId(omemoManager, lastPreKeyId + newKeysCount); 205 } 206 207 return new OmemoBundleVAxolotlElement( 208 currentSignedPreKeyId, 209 keyUtil().signedPreKeyPublicForBundle(currentSignedPreKey), 210 keyUtil().signedPreKeySignatureFromKey(currentSignedPreKey), 211 keyUtil().identityKeyForBundle(keyUtil().identityKeyFromPair(identityKeyPair)), 212 keyUtil().preKeyPublisKeysForBundle(preKeys) 213 ); 214 } 215 216 /** 217 * Preload all OMEMO sessions for our devices and our contacts from existing raw sessions. 218 * 219 * @param omemoManager omemoManager of our device. 220 */ 221 void initializeOmemoSessions(OmemoManager omemoManager) { 222 223 // Get HashMap of our omemoSessions 224 HashMap<OmemoDevice, OmemoSession<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph>> 225 sessions = omemoSessions.get(omemoManager); 226 if (sessions == null) { 227 sessions = new HashMap<>(); 228 omemoSessions.put(omemoManager, sessions); 229 } 230 231 // Sessions with our own devices 232 HashMap<Integer, T_Sess> ourRawSessions = loadAllRawSessionsOf(omemoManager, omemoManager.getOwnJid()); 233 ourRawSessions.remove(omemoManager.getDeviceId()); //Just to make sure we have no session with ourselves... 234 sessions.putAll(createOmemoSessionsFromRawSessions(omemoManager, omemoManager.getOwnJid(), ourRawSessions)); 235 236 // Sessions with contacts 237 for (RosterEntry rosterEntry : Roster.getInstanceFor(omemoManager.getConnection()).getEntries()) { 238 HashMap<Integer, T_Sess> contactDevices = loadAllRawSessionsOf(omemoManager, rosterEntry.getJid().asBareJid()); 239 sessions.putAll(createOmemoSessionsFromRawSessions(omemoManager, rosterEntry.getJid().asBareJid(), contactDevices)); 240 } 241 } 242 243 /** 244 * Forget all omemoSessions of the omemoManager from cache. 245 * This will not remove the sessions from persistent memory! 246 * 247 * @param omemoManager omemoManager we want to forget sessions from. 248 */ 249 void forgetOmemoSessions(OmemoManager omemoManager) { 250 omemoSessions.remove(omemoManager); 251 } 252 253 /** 254 * Create a new concrete OmemoSession with a contact. 255 * 256 * @param omemoManager omemoManager of our device. 257 * @param device device to establish the session with 258 * @param identityKey identityKey of the device 259 * @return concrete OmemoSession 260 */ 261 private OmemoSession<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph> 262 createOmemoSession(OmemoManager omemoManager, OmemoDevice device, T_IdKey identityKey) { 263 return keyUtil().createOmemoSession(omemoManager, this, device, identityKey); 264 } 265 266 /** 267 * Return the OmemoSession for the OmemoDevice. If there is no OmemoSession for the device yet, 268 * build one from local raw session material. 269 * 270 * @param omemoManager omemoManager of our device. 271 * @param device OmemoDevice 272 * @return OmemoSession 273 */ 274 public OmemoSession<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph> 275 getOmemoSessionOf(OmemoManager omemoManager, OmemoDevice device) { 276 277 HashMap<OmemoDevice, OmemoSession<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph>> 278 sessions = omemoSessions.get(omemoManager); 279 280 if (sessions == null) { 281 sessions = new HashMap<>(); 282 omemoSessions.put(omemoManager, sessions); 283 } 284 285 OmemoSession<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph> 286 session = sessions.get(device); 287 // No OmemoSession found 288 if (session == null) { 289 T_IdKey identityKey = null; 290 try { 291 identityKey = loadOmemoIdentityKey(omemoManager, device); 292 } catch (CorruptedOmemoKeyException e) { 293 LOGGER.log(Level.WARNING, "getOmemoSessionOf could not load identityKey of " + device + ": " + e.getMessage()); 294 } 295 296 if (identityKey != null) { 297 session = createOmemoSession(omemoManager, device, identityKey); 298 299 } else { 300 LOGGER.log(Level.INFO, "getOmemoSessionOf couldn't find an identityKey for " + device 301 + ". Initiate session without."); 302 session = createOmemoSession(omemoManager, device, null); 303 } 304 305 sessions.put(device, session); 306 } 307 308 if (session.getIdentityKey() == null) { 309 try { 310 session.setIdentityKey(loadOmemoIdentityKey(omemoManager, device)); 311 } catch (CorruptedOmemoKeyException e) { 312 LOGGER.log(Level.WARNING, "Can't update IdentityKey of " + device + ": " + e.getMessage()); 313 } 314 } 315 return session; 316 } 317 318 /** 319 * Create OmemoSession objects for all T_Sess objects of the contact. 320 * The T_Sess objects will be wrapped inside a OmemoSession for every device of the contact. 321 * 322 * @param omemoManager omemoManager of our device. 323 * @param contact BareJid of the contact 324 * @param rawSessions HashMap of Integers (deviceIds) and T_Sess sessions. 325 * @return HashMap of OmemoContacts and OmemoSessions 326 */ 327 private HashMap<OmemoDevice, OmemoSession<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph>> 328 createOmemoSessionsFromRawSessions(OmemoManager omemoManager, BareJid contact, HashMap<Integer, T_Sess> rawSessions) { 329 330 HashMap<OmemoDevice, OmemoSession<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph>> 331 sessions = new HashMap<>(); 332 333 for (Map.Entry<Integer, T_Sess> sessionEntry : rawSessions.entrySet()) { 334 OmemoDevice omemoDevice = new OmemoDevice(contact, sessionEntry.getKey()); 335 try { 336 T_IdKey identityKey = loadOmemoIdentityKey(omemoManager, omemoDevice); 337 if (identityKey != null) { 338 sessions.put(omemoDevice, createOmemoSession(omemoManager, omemoDevice, identityKey)); 339 } else { 340 LOGGER.log(Level.WARNING, "IdentityKey of " + omemoDevice + " is null. Is this even possible at this point?"); 341 } 342 } catch (CorruptedOmemoKeyException e1) { 343 LOGGER.log(Level.WARNING, "buildOmemoSessionFor could not create a session for " + omemoDevice + 344 ": " + e1.getMessage()); 345 } 346 } 347 return sessions; 348 } 349 350 // *sigh* 351 352 /** 353 * Return the id of the last generated preKey. 354 * This is used to generate new preKeys without preKeyId collisions. 355 * 356 * @param omemoManager omemoManager of our device. 357 * @return id of the last preKey 358 */ 359 public abstract int loadLastPreKeyId(OmemoManager omemoManager); 360 361 /** 362 * Store the id of the last preKey we generated. 363 * 364 * @param omemoManager omemoManager of our device. 365 * @param currentPreKeyId the id of the last generated PreKey 366 */ 367 public abstract void storeLastPreKeyId(OmemoManager omemoManager, int currentPreKeyId); 368 369 /** 370 * Generate a new IdentityKeyPair. We should always have only one pair and usually keep this for a long time. 371 * 372 * @return identityKeyPair 373 */ 374 public T_IdKeyPair generateOmemoIdentityKeyPair() { 375 return keyUtil().generateOmemoIdentityKeyPair(); 376 } 377 378 /** 379 * Load our identityKeyPair from storage. 380 * 381 * @param omemoManager omemoManager of our device. 382 * @return identityKeyPair 383 * @throws CorruptedOmemoKeyException Thrown, if the stored key is damaged (*hands up* not my fault!) 384 */ 385 public abstract T_IdKeyPair loadOmemoIdentityKeyPair(OmemoManager omemoManager) throws CorruptedOmemoKeyException; 386 387 /** 388 * Store our identityKeyPair in storage. It would be a cool feature, if the key could be stored in a encrypted 389 * database or something similar. 390 * 391 * @param omemoManager omemoManager of our device. 392 * @param identityKeyPair identityKeyPair 393 */ 394 public abstract void storeOmemoIdentityKeyPair(OmemoManager omemoManager, T_IdKeyPair identityKeyPair); 395 396 /** 397 * Load the public identityKey of the device. 398 * 399 * @param omemoManager omemoManager of our device. 400 * @param device device 401 * @return identityKey 402 * @throws CorruptedOmemoKeyException when the key in question is corrupted and cant be deserialized. 403 */ 404 public abstract T_IdKey loadOmemoIdentityKey(OmemoManager omemoManager, OmemoDevice device) throws CorruptedOmemoKeyException; 405 406 /** 407 * Store the public identityKey of the device. 408 * 409 * @param omemoManager omemoManager of our device. 410 * @param device device 411 * @param key identityKey 412 */ 413 public abstract void storeOmemoIdentityKey(OmemoManager omemoManager, OmemoDevice device, T_IdKey key); 414 415 /** 416 * Decide, whether a identityKey of a device is trusted or not. 417 * If you want to use this module, you should memorize, whether the user has trusted this key or not, since 418 * the owner of the identityKey will be able to read sent messages when this method returned 'true' for their 419 * identityKey. Either you let the user decide whether you trust a key every time you see a new key, or you 420 * implement something like 'blind trust' (see https://gultsch.de/trust.html). 421 * 422 * @param omemoManager omemoManager of our device. 423 * @param device Owner of the key 424 * @param identityKey identityKey 425 * @return true, if the user trusts the key and wants to send messages to it, otherwise false 426 */ 427 public boolean isTrustedOmemoIdentity(OmemoManager omemoManager, OmemoDevice device, T_IdKey identityKey) { 428 return isTrustedOmemoIdentity(omemoManager, device, keyUtil().getFingerprint(identityKey)); 429 } 430 431 public abstract boolean isTrustedOmemoIdentity(OmemoManager omemoManager, OmemoDevice device, OmemoFingerprint fingerprint); 432 433 /** 434 * Did the user yet made a decision about whether to trust or distrust this device? 435 * 436 * @param omemoManager omemoManager of our device. 437 * @param device device 438 * @param identityKey IdentityKey 439 * @return true, if the user either trusted or distrusted the device. Return false, if the user did not yet decide. 440 */ 441 public boolean isDecidedOmemoIdentity(OmemoManager omemoManager, OmemoDevice device, T_IdKey identityKey) { 442 return isDecidedOmemoIdentity(omemoManager, device, keyUtil().getFingerprint(identityKey)); 443 } 444 445 public abstract boolean isDecidedOmemoIdentity(OmemoManager omemoManager, OmemoDevice device, OmemoFingerprint fingerprint); 446 447 /** 448 * Trust an OmemoIdentity. This involves marking the key as trusted. 449 * 450 * @param omemoManager omemoManager of our device. 451 * @param device device 452 * @param identityKey identityKey 453 */ 454 public void trustOmemoIdentity(OmemoManager omemoManager, OmemoDevice device, T_IdKey identityKey) { 455 trustOmemoIdentity(omemoManager, device, keyUtil().getFingerprint(identityKey)); 456 } 457 458 public abstract void trustOmemoIdentity(OmemoManager omemoManager, OmemoDevice device, OmemoFingerprint identityKeyFingerprint); 459 460 /** 461 * Distrust an OmemoIdentity. This involved marking the key as distrusted. 462 * 463 * @param omemoManager omemoManager of our device. 464 * @param device device 465 * @param identityKey identityKey 466 */ 467 public void distrustOmemoIdentity(OmemoManager omemoManager, OmemoDevice device, T_IdKey identityKey) { 468 distrustOmemoIdentity(omemoManager, device, keyUtil().getFingerprint(identityKey)); 469 } 470 471 public abstract void distrustOmemoIdentity(OmemoManager omemoManager, OmemoDevice device, OmemoFingerprint fingerprint); 472 473 /** 474 * Set the date in millis of the last message that was received from device 'from' to 'date'. 475 * 476 * @param omemoManager omemoManager of our device. 477 * @param from device in question 478 * @param date date of the last received message 479 */ 480 public abstract void setDateOfLastReceivedMessage(OmemoManager omemoManager, OmemoDevice from, Date date); 481 482 /** 483 * Set the date in millis of the last message that was received from device 'from' to now. 484 * 485 * @param omemoManager omemoManager of our device. 486 * @param from device in question 487 */ 488 public void setDateOfLastReceivedMessage(OmemoManager omemoManager, OmemoDevice from) { 489 this.setDateOfLastReceivedMessage(omemoManager, from, new Date()); 490 } 491 492 /** 493 * Return the date in millis of the last message that was received from device 'from'. 494 * 495 * @param omemoManager omemoManager of our device. 496 * @param from device in question 497 * @return date if existent as long, otherwise -1 498 */ 499 public abstract Date getDateOfLastReceivedMessage(OmemoManager omemoManager, OmemoDevice from); 500 501 /** 502 * Set the date in millis of the last time the signed preKey was renewed. 503 * 504 * @param omemoManager omemoManager of our device. 505 * @param date date 506 */ 507 public abstract void setDateOfLastSignedPreKeyRenewal(OmemoManager omemoManager, Date date); 508 509 /** 510 * Store the date of the last preKey renewal in the omemoStore. 511 * 512 * @param omemoManager omemoManager of our device. 513 */ 514 public void setDateOfLastSignedPreKeyRenewal(OmemoManager omemoManager) { 515 setDateOfLastSignedPreKeyRenewal(omemoManager, new Date()); 516 } 517 518 /** 519 * Get the date in millis of the last time the signed preKey was renewed. 520 * 521 * @param omemoManager omemoManager of our device. 522 * @return date if existent, otherwise null 523 */ 524 public abstract Date getDateOfLastSignedPreKeyRenewal(OmemoManager omemoManager); 525 526 /** 527 * Generate 'count' new PreKeys beginning with id 'startId'. 528 * These preKeys are published and can be used by contacts to establish sessions with us. 529 * 530 * @param startId start id 531 * @param count how many keys do we want to generate 532 * @return Map of new preKeys 533 */ 534 public HashMap<Integer, T_PreKey> generateOmemoPreKeys(int startId, int count) { 535 return keyUtil().generateOmemoPreKeys(startId, count); 536 } 537 538 /** 539 * Load the preKey with id 'preKeyId' from storage. 540 * 541 * @param omemoManager omemoManager of our device. 542 * @param preKeyId id of the key to be loaded 543 * @return loaded preKey 544 */ 545 public abstract T_PreKey loadOmemoPreKey(OmemoManager omemoManager, int preKeyId); 546 547 /** 548 * Store a PreKey in storage. 549 * 550 * @param omemoManager omemoManager of our device. 551 * @param preKeyId id of the key 552 * @param preKey key 553 */ 554 public abstract void storeOmemoPreKey(OmemoManager omemoManager, int preKeyId, T_PreKey preKey); 555 556 /** 557 * Store a whole bunch of preKeys. 558 * 559 * @param omemoManager omemoManager of our device. 560 * @param preKeyHashMap HashMap of preKeys 561 */ 562 public void storeOmemoPreKeys(OmemoManager omemoManager, HashMap<Integer, T_PreKey> preKeyHashMap) { 563 for (Map.Entry<Integer, T_PreKey> e : preKeyHashMap.entrySet()) { 564 storeOmemoPreKey(omemoManager, e.getKey(), e.getValue()); 565 } 566 } 567 568 /** 569 * remove a preKey from storage. This is called, when a contact used one of our preKeys to establish a session 570 * with us. 571 * 572 * @param omemoManager omemoManager of our device. 573 * @param preKeyId id of the used key that will be deleted 574 */ 575 public abstract void removeOmemoPreKey(OmemoManager omemoManager, int preKeyId); 576 577 /** 578 * Return the id of the currently used signed preKey. 579 * This is used to avoid collisions when generating a new signedPreKey. 580 * 581 * @param omemoManager omemoManager of our device. 582 * @return id 583 */ 584 public abstract int loadCurrentSignedPreKeyId(OmemoManager omemoManager); 585 586 /** 587 * Store the id of the currently used signedPreKey. 588 * 589 * @param omemoManager omemoManager of our device. 590 * @param currentSignedPreKeyId if of the signedPreKey that is currently in use 591 */ 592 public abstract void storeCurrentSignedPreKeyId(OmemoManager omemoManager, int currentSignedPreKeyId); 593 594 /** 595 * Return all our current OmemoPreKeys. 596 * 597 * @param omemoManager omemoManager of our device. 598 * @return Map containing our preKeys 599 */ 600 public abstract HashMap<Integer, T_PreKey> loadOmemoPreKeys(OmemoManager omemoManager); 601 602 /** 603 * Return the signedPreKey with the id 'singedPreKeyId'. 604 * 605 * @param omemoManager omemoManager of our device. 606 * @param signedPreKeyId id of the key 607 * @return key 608 */ 609 public abstract T_SigPreKey loadOmemoSignedPreKey(OmemoManager omemoManager, int signedPreKeyId); 610 611 /** 612 * Load all our signed PreKeys. 613 * 614 * @param omemoManager omemoManager of our device. 615 * @return HashMap of our singedPreKeys 616 */ 617 public abstract HashMap<Integer, T_SigPreKey> loadOmemoSignedPreKeys(OmemoManager omemoManager); 618 619 /** 620 * Generate a new signed preKey. 621 * 622 * @param identityKeyPair identityKeyPair used to sign the preKey 623 * @param signedPreKeyId id that the preKey will have 624 * @return signedPreKey 625 * @throws CorruptedOmemoKeyException when something goes wrong 626 */ 627 public T_SigPreKey generateOmemoSignedPreKey(T_IdKeyPair identityKeyPair, int signedPreKeyId) throws CorruptedOmemoKeyException { 628 return keyUtil().generateOmemoSignedPreKey(identityKeyPair, signedPreKeyId); 629 } 630 631 /** 632 * Store a signedPreKey in storage. 633 * 634 * @param omemoManager omemoManager of our device. 635 * @param signedPreKeyId id of the signedPreKey 636 * @param signedPreKey the key itself 637 */ 638 public abstract void storeOmemoSignedPreKey(OmemoManager omemoManager, int signedPreKeyId, T_SigPreKey signedPreKey); 639 640 /** 641 * Remove a signedPreKey from storage. 642 * 643 * @param omemoManager omemoManager of our device. 644 * @param signedPreKeyId id of the key that will be removed 645 */ 646 public abstract void removeOmemoSignedPreKey(OmemoManager omemoManager, int signedPreKeyId); 647 648 /** 649 * Load the crypto-lib specific session object of the device from storage. 650 * 651 * @param omemoManager omemoManager of our device. 652 * @param device device whose session we want to load 653 * @return crypto related session 654 */ 655 public abstract T_Sess loadRawSession(OmemoManager omemoManager, OmemoDevice device); 656 657 /** 658 * Load all crypto-lib specific session objects of contact 'contact'. 659 * 660 * @param omemoManager omemoManager of our device. 661 * @param contact BareJid of the contact we want to get all sessions from 662 * @return HashMap of deviceId and sessions of the contact 663 */ 664 public abstract HashMap<Integer, T_Sess> loadAllRawSessionsOf(OmemoManager omemoManager, BareJid contact); 665 666 /** 667 * Store a crypto-lib specific session to storage. 668 * 669 * @param omemoManager omemoManager of our device. 670 * @param device OmemoDevice whose session we want to store 671 * @param session session 672 */ 673 public abstract void storeRawSession(OmemoManager omemoManager, OmemoDevice device, T_Sess session); 674 675 /** 676 * Remove a crypto-lib specific session from storage. 677 * 678 * @param omemoManager omemoManager of our device. 679 * @param device device whose session we want to delete 680 */ 681 public abstract void removeRawSession(OmemoManager omemoManager, OmemoDevice device); 682 683 /** 684 * Remove all crypto-lib specific session of a contact. 685 * 686 * @param omemoManager omemoManager of our device. 687 * @param contact BareJid of the contact 688 */ 689 public abstract void removeAllRawSessionsOf(OmemoManager omemoManager, BareJid contact); 690 691 /** 692 * Return true, if we have a session with the device, otherwise false. 693 * Hint for Signal: Do not try 'return getSession() != null' since this will create a new session. 694 * 695 * @param omemoManager omemoManager of our device. 696 * @param device device 697 * @return true if we have session, otherwise false 698 */ 699 public abstract boolean containsRawSession(OmemoManager omemoManager, OmemoDevice device); 700 701 /** 702 * Load a list of deviceIds from contact 'contact' from the local cache. 703 * 704 * @param omemoManager omemoManager of our device. 705 * @param contact contact we want to get the deviceList of 706 * @return CachedDeviceList of the contact 707 */ 708 public abstract CachedDeviceList loadCachedDeviceList(OmemoManager omemoManager, BareJid contact); 709 710 /** 711 * Store the DeviceList of the contact in local storage. 712 * See this as a cache. 713 * 714 * @param omemoManager omemoManager of our device. 715 * @param contact Contact 716 * @param deviceList list of the contacts devices' ids. 717 */ 718 public abstract void storeCachedDeviceList(OmemoManager omemoManager, BareJid contact, CachedDeviceList deviceList); 719 720 /** 721 * Delete this device's IdentityKey, PreKeys, SignedPreKeys and Sessions. 722 * 723 * @param omemoManager omemoManager of our device. 724 */ 725 public abstract void purgeOwnDeviceKeys(OmemoManager omemoManager); 726 727 /** 728 * Return a concrete KeyUtil object that we can use as a utility to create keys etc. 729 * 730 * @return KeyUtil object 731 */ 732 public abstract OmemoKeyUtil<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph> keyUtil(); 733 734 /** 735 * Return our identityKeys fingerprint. 736 * 737 * @param omemoManager omemoManager of our device. 738 * @return fingerprint of our identityKeyPair 739 */ 740 public OmemoFingerprint getFingerprint(OmemoManager omemoManager) { 741 try { 742 return keyUtil().getFingerprint(keyUtil().identityKeyFromPair(loadOmemoIdentityKeyPair(omemoManager))); 743 744 } catch (CorruptedOmemoKeyException e) { 745 LOGGER.log(Level.WARNING, "getFingerprint failed due to corrupted identityKeyPair: " + e.getMessage()); 746 return null; 747 } 748 } 749 750 /** 751 * Return the default deviceId for a user. 752 * The defaultDeviceId will be used when the OmemoManager gets instantiated without passing a specific deviceId. 753 * If no default id is set, return -1; 754 * 755 * @param user user 756 * @return defaultDeviceId or -1 757 */ 758 public abstract int getDefaultDeviceId(BareJid user); 759 760 /** 761 * Set the default deviceId of a user. 762 * 763 * @param user user 764 * @param defaultDeviceId defaultDeviceId 765 */ 766 public abstract void setDefaultDeviceId(BareJid user, int defaultDeviceId); 767 768 /** 769 * Return the fingerprint of the given devices announced identityKey. 770 * 771 * @param omemoManager omemoManager of our device. 772 * @param device device 773 * @throws CannotEstablishOmemoSessionException if we cannot establish a session 774 * @return fingerprint of the identityKey 775 */ 776 public OmemoFingerprint getFingerprint(OmemoManager omemoManager, OmemoDevice device) throws CannotEstablishOmemoSessionException { 777 T_IdKey idKey; 778 779 try { 780 idKey = loadOmemoIdentityKey(omemoManager, device); 781 if (idKey == null) { 782 OmemoService.getInstance().buildSessionFromOmemoBundle(omemoManager, device, true); 783 } 784 idKey = loadOmemoIdentityKey(omemoManager, device); 785 } catch (CorruptedOmemoKeyException e) { 786 LOGGER.log(Level.WARNING, "getFingerprint failed due to corrupted identityKey: " + e.getMessage()); 787 return null; 788 } 789 return keyUtil().getFingerprint(idKey); 790 } 791}