]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/helper/PinHelper.java
Use .isEmpty() for checking lists and strings
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / helper / PinHelper.java
1 package org.asamk.signal.manager.helper;
2
3 import org.asamk.signal.manager.api.IncorrectPinException;
4 import org.slf4j.Logger;
5 import org.slf4j.LoggerFactory;
6 import org.whispersystems.signalservice.api.KeyBackupService;
7 import org.whispersystems.signalservice.api.kbs.MasterKey;
8 import org.whispersystems.signalservice.api.svr.SecureValueRecovery;
9 import org.whispersystems.signalservice.api.svr.SecureValueRecoveryV1;
10 import org.whispersystems.signalservice.api.svr.SecureValueRecoveryV2;
11 import org.whispersystems.signalservice.internal.push.AuthCredentials;
12 import org.whispersystems.signalservice.internal.push.LockedException;
13
14 import java.io.IOException;
15 import java.util.Collection;
16
17 public class PinHelper {
18
19 private final static Logger logger = LoggerFactory.getLogger(PinHelper.class);
20
21 private final SecureValueRecoveryV1 secureValueRecoveryV1;
22 private final SecureValueRecoveryV2 secureValueRecoveryV2;
23 private final Collection<KeyBackupService> fallbackKeyBackupServices;
24
25 public PinHelper(
26 final SecureValueRecoveryV1 secureValueRecoveryV1,
27 final SecureValueRecoveryV2 secureValueRecoveryV2,
28 final Collection<KeyBackupService> fallbackKeyBackupServices
29 ) {
30 this.fallbackKeyBackupServices = fallbackKeyBackupServices;
31 this.secureValueRecoveryV1 = secureValueRecoveryV1;
32 this.secureValueRecoveryV2 = secureValueRecoveryV2;
33 }
34
35 public void setRegistrationLockPin(
36 String pin, MasterKey masterKey
37 ) throws IOException {
38 secureValueRecoveryV1.setPin(pin, masterKey).execute();
39 final var backupResponse = secureValueRecoveryV2.setPin(pin, masterKey).execute();
40 if (backupResponse instanceof SecureValueRecovery.BackupResponse.Success) {
41 } else if (backupResponse instanceof SecureValueRecovery.BackupResponse.ServerRejected) {
42 logger.warn("Backup svr2 failed: ServerRejected");
43 } else if (backupResponse instanceof SecureValueRecovery.BackupResponse.EnclaveNotFound) {
44 logger.warn("Backup svr2 failed: EnclaveNotFound");
45 } else if (backupResponse instanceof SecureValueRecovery.BackupResponse.ExposeFailure) {
46 logger.warn("Backup svr2 failed: ExposeFailure");
47 } else if (backupResponse instanceof SecureValueRecovery.BackupResponse.ApplicationError error) {
48 throw new IOException(error.getException());
49 } else if (backupResponse instanceof SecureValueRecovery.BackupResponse.NetworkError error) {
50 throw error.getException();
51 } else {
52 throw new AssertionError("Unexpected response");
53 }
54 }
55
56 public void migrateRegistrationLockPin(String pin, MasterKey masterKey) throws IOException {
57 setRegistrationLockPin(pin, masterKey);
58
59 for (final var keyBackupService : fallbackKeyBackupServices) {
60 try {
61 final var pinChangeSession = keyBackupService.newPinChangeSession();
62 pinChangeSession.removePin();
63 } catch (Exception e) {
64 logger.warn("Failed to remove PIN from fallback KBS: {}", e.getMessage());
65 }
66 }
67 }
68
69 public void removeRegistrationLockPin() throws IOException {
70 secureValueRecoveryV1.deleteData();
71 final var deleteResponse = secureValueRecoveryV2.deleteData();
72 if (deleteResponse instanceof SecureValueRecovery.DeleteResponse.Success) {
73 } else if (deleteResponse instanceof SecureValueRecovery.DeleteResponse.ServerRejected) {
74 logger.warn("Delete svr2 failed: ServerRejected");
75 } else if (deleteResponse instanceof SecureValueRecovery.DeleteResponse.EnclaveNotFound) {
76 logger.warn("Delete svr2 failed: EnclaveNotFound");
77 } else if (deleteResponse instanceof SecureValueRecovery.DeleteResponse.ApplicationError error) {
78 throw new IOException(error.getException());
79 } else if (deleteResponse instanceof SecureValueRecovery.DeleteResponse.NetworkError error) {
80 throw error.getException();
81 } else {
82 throw new AssertionError("Unexpected response");
83 }
84 }
85
86 public SecureValueRecovery.RestoreResponse.Success getRegistrationLockData(
87 String pin, LockedException e
88 ) throws IOException, IncorrectPinException {
89 var svr1Credentials = e.getSvr1Credentials();
90 if (svr1Credentials != null) {
91 final var registrationLockData = getRegistrationLockData(secureValueRecoveryV1, svr1Credentials, pin);
92 if (registrationLockData != null) {
93 return registrationLockData;
94 }
95 }
96
97 var svr2Credentials = e.getSvr2Credentials();
98 if (svr2Credentials != null) {
99 return getRegistrationLockData(secureValueRecoveryV2, svr2Credentials, pin);
100 }
101
102 return null;
103 }
104
105 public SecureValueRecovery.RestoreResponse.Success getRegistrationLockData(
106 SecureValueRecovery secureValueRecovery, AuthCredentials authCredentials, String pin
107 ) throws IOException, IncorrectPinException {
108 final var restoreResponse = secureValueRecovery.restoreDataPreRegistration(authCredentials, pin);
109
110 if (restoreResponse instanceof SecureValueRecovery.RestoreResponse.Success s) {
111 return s;
112 } else if (restoreResponse instanceof SecureValueRecovery.RestoreResponse.PinMismatch pinMismatch) {
113 throw new IncorrectPinException(pinMismatch.getTriesRemaining());
114 } else if (restoreResponse instanceof SecureValueRecovery.RestoreResponse.ApplicationError error) {
115 throw new IOException(error.getException());
116 } else if (restoreResponse instanceof SecureValueRecovery.RestoreResponse.NetworkError error) {
117 throw error.getException();
118 } else if (restoreResponse instanceof SecureValueRecovery.RestoreResponse.Missing) {
119 logger.debug("No SVR data stored for the given credentials.");
120 return null;
121 } else {
122 throw new AssertionError("Unexpected response: " + restoreResponse.getClass().getSimpleName());
123 }
124 }
125 }