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 019/** 020 * Contains OMEMO related configuration options. 021 * 022 * @author Paul Schaub 023 */ 024public final class OmemoConfiguration { 025 026 private static boolean IGNORE_READ_ONLY_DEVICES = true; 027 private static int MAX_READ_ONLY_MESSAGE_COUNT = 400; 028 029 /** 030 * Set to true, in order to ignore read-only devices. 031 * 032 * @param ignore ignore read-only devices 033 * @see <a href="https://blog.jabberhead.tk/2019/12/13/pitfalls-for-omemo-implementations-part-1-inactive-devices/">Blog Post explaining the danger of read-only devices.</a> 034 */ 035 public static void setIgnoreReadOnlyDevices(boolean ignore) { 036 IGNORE_READ_ONLY_DEVICES = ignore; 037 } 038 039 /** 040 * Return true, if the client should stop encrypting messages to a read-only device. 041 * 042 * @return true if read-only devices should get ignored after a certain amount of unanswered messages. 043 * @see <a href="https://blog.jabberhead.tk/2019/12/13/pitfalls-for-omemo-implementations-part-1-inactive-devices/">Blog Post explaining the danger of read-only devices.</a> 044 */ 045 public static boolean getIgnoreReadOnlyDevices() { 046 return IGNORE_READ_ONLY_DEVICES; 047 } 048 049 /** 050 * Set the maximum amount of messages that the client is allowed to send to a read-only device without getting a 051 * response. Once the message counter of a device reaches that value, the client will stop encrypting messages for 052 * the device (given that {@link #getIgnoreReadOnlyDevices()} is true). 053 * This threshold is used to prevent read-only devices from weakening forward secrecy. 054 * 055 * @param maxReadOnlyMessageCount maximum number of allowed messages to a read-only device. 056 * @see <a href="https://blog.jabberhead.tk/2019/12/13/pitfalls-for-omemo-implementations-part-1-inactive-devices/">Blog Post explaining the danger of read-only devices.</a> 057 */ 058 public static void setMaxReadOnlyMessageCount(int maxReadOnlyMessageCount) { 059 if (maxReadOnlyMessageCount <= 0) { 060 throw new IllegalArgumentException("maxReadOnlyMessageCount MUST be greater than 0."); 061 } 062 MAX_READ_ONLY_MESSAGE_COUNT = maxReadOnlyMessageCount; 063 } 064 065 /** 066 * Get the maximum amount of messages that the client is allowed to send to a read-only device without getting a 067 * response. Once the message counter of a device reaches that value, the client will stop encrypting messages for 068 * the device (given that {@link #getIgnoreReadOnlyDevices()} is true). 069 * This threshold is used to prevent read-only devices from weakening forward secrecy. 070 * 071 * @return maximum number of allowed messages to a read-only device. 072 * @see <a href="https://blog.jabberhead.tk/2019/12/13/pitfalls-for-omemo-implementations-part-1-inactive-devices/">Blog Post explaining the danger of read-only devices.</a> 073 */ 074 public static int getMaxReadOnlyMessageCount() { 075 return MAX_READ_ONLY_MESSAGE_COUNT; 076 } 077 078 /** 079 * Delete stale devices from the device list after a period of time. 080 */ 081 private static boolean DELETE_STALE_DEVICES = true; 082 private static int DELETE_STALE_DEVICE_AFTER_HOURS = 24 * 7 * 4; //4 weeks 083 084 public static void setDeleteStaleDevices(boolean delete) { 085 DELETE_STALE_DEVICES = delete; 086 } 087 088 public static boolean getDeleteStaleDevices() { 089 return DELETE_STALE_DEVICES; 090 } 091 092 public static void setDeleteStaleDevicesAfterHours(int hours) { 093 if (hours <= 0) { 094 throw new IllegalArgumentException("Hours must be greater than 0."); 095 } 096 DELETE_STALE_DEVICE_AFTER_HOURS = hours; 097 } 098 099 public static int getDeleteStaleDevicesAfterHours() { 100 return DELETE_STALE_DEVICE_AFTER_HOURS; 101 } 102 103 /** 104 * Upload a new signed prekey in intervals. This improves forward secrecy. Old keys are kept for some more time and 105 * then deleted. 106 */ 107 private static boolean RENEW_OLD_SIGNED_PREKEYS = false; 108 private static int RENEW_OLD_SIGNED_PREKEYS_AFTER_HOURS = 24 * 7; //One week 109 private static int MAX_NUMBER_OF_STORED_SIGNED_PREKEYS = 4; 110 111 /** 112 * Decide, whether signed preKeys are automatically rotated or not. 113 * It is highly recommended to rotate signed preKeys to preserve forward secrecy. 114 * 115 * @param renew automatically rotate signed preKeys? 116 */ 117 public static void setRenewOldSignedPreKeys(boolean renew) { 118 RENEW_OLD_SIGNED_PREKEYS = renew; 119 } 120 121 /** 122 * Determine, whether signed preKeys are automatically rotated or not. 123 * 124 * @return auto-rotate signed preKeys? 125 */ 126 public static boolean getRenewOldSignedPreKeys() { 127 return RENEW_OLD_SIGNED_PREKEYS; 128 } 129 130 /** 131 * Set the interval in hours, after which the published signed preKey should be renewed. 132 * This value should be between one or two weeks. 133 * 134 * @param hours hours after which signed preKeys should be rotated. 135 */ 136 public static void setRenewOldSignedPreKeysAfterHours(int hours) { 137 if (hours <= 0) { 138 throw new IllegalArgumentException("Hours must be greater than 0."); 139 } 140 RENEW_OLD_SIGNED_PREKEYS_AFTER_HOURS = hours; 141 } 142 143 /** 144 * Get the interval in hours, after which the published signed preKey should be renewed. 145 * This value should be between one or two weeks. 146 * 147 * @return hours after which signed preKeys should be rotated. 148 */ 149 public static int getRenewOldSignedPreKeysAfterHours() { 150 return RENEW_OLD_SIGNED_PREKEYS_AFTER_HOURS; 151 } 152 153 /** 154 * Set the maximum number of signed preKeys that are cached until the oldest one gets deleted. 155 * This number should not be too small in order to prevent message loss, but also not too big 156 * to preserve forward secrecy. 157 * 158 * @param number number of cached signed preKeys. 159 */ 160 public static void setMaxNumberOfStoredSignedPreKeys(int number) { 161 if (number <= 0) { 162 throw new IllegalArgumentException("Number must be greater than 0."); 163 } 164 MAX_NUMBER_OF_STORED_SIGNED_PREKEYS = number; 165 } 166 167 /** 168 * Return the maximum number of signed preKeys that are cached until the oldest one gets deleted. 169 * @return max number of cached signed preKeys. 170 */ 171 public static int getMaxNumberOfStoredSignedPreKeys() { 172 return MAX_NUMBER_OF_STORED_SIGNED_PREKEYS; 173 } 174 175 /** 176 * Add a plaintext body hint about omemo encryption to the message. 177 */ 178 private static boolean ADD_OMEMO_HINT_BODY = true; 179 180 /** 181 * Decide, whether an OMEMO message should carry a plaintext hint about OMEMO encryption. 182 * Eg. "I sent you an OMEMO encrypted message..." 183 * 184 * @param addHint shall we add a hint? 185 */ 186 public static void setAddOmemoHintBody(boolean addHint) { 187 ADD_OMEMO_HINT_BODY = addHint; 188 } 189 190 /** 191 * Determine, whether an OMEMO message should carry a plaintext hint about OMEMO encryption. 192 * 193 * @return true, if a hint is added to the message. 194 */ 195 public static boolean getAddOmemoHintBody() { 196 return ADD_OMEMO_HINT_BODY; 197 } 198 199 private static boolean REPAIR_BROKEN_SESSIONS_WITH_PREKEY_MESSAGES = true; 200 201 /** 202 * Determine, whether incoming messages, which have broken sessions should automatically be answered by an empty 203 * preKeyMessage in order to establish a new session. 204 * 205 * @return true if session should be repaired automatically. 206 */ 207 public static boolean getRepairBrokenSessionsWithPreKeyMessages() { 208 return REPAIR_BROKEN_SESSIONS_WITH_PREKEY_MESSAGES; 209 } 210 211 /** 212 * Decide, whether incoming messages, which have broken sessions should automatically be answered by an empty 213 * preKeyMessage in order to establish a new session. 214 * 215 * @param repair repair sessions? 216 */ 217 public static void setRepairBrokenSessionsWithPrekeyMessages(boolean repair) { 218 REPAIR_BROKEN_SESSIONS_WITH_PREKEY_MESSAGES = repair; 219 } 220 221 private static boolean COMPLETE_SESSION_WITH_EMPTY_MESSAGE = true; 222 223 /** 224 * Determine, whether incoming preKeyMessages should automatically be answered by an empty message in order to 225 * complete the session. 226 * 227 * @return true if sessions should be completed. 228 */ 229 public static boolean getCompleteSessionWithEmptyMessage() { 230 return COMPLETE_SESSION_WITH_EMPTY_MESSAGE; 231 } 232 233 /** 234 * Decide, whether incoming preKeyMessages should automatically be answered by an empty message in order to 235 * complete the session. 236 * 237 * @param complete complete the session or not 238 */ 239 public static void setCompleteSessionWithEmptyMessage(boolean complete) { 240 COMPLETE_SESSION_WITH_EMPTY_MESSAGE = complete; 241 } 242}