1 package org
.asamk
.signal
.manager
.helper
;
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
;
14 import java
.io
.IOException
;
15 import java
.util
.Collection
;
17 public class PinHelper
{
19 private final static Logger logger
= LoggerFactory
.getLogger(PinHelper
.class);
21 private final SecureValueRecoveryV1 secureValueRecoveryV1
;
22 private final SecureValueRecoveryV2 secureValueRecoveryV2
;
23 private final Collection
<KeyBackupService
> fallbackKeyBackupServices
;
26 final SecureValueRecoveryV1 secureValueRecoveryV1
,
27 final SecureValueRecoveryV2 secureValueRecoveryV2
,
28 final Collection
<KeyBackupService
> fallbackKeyBackupServices
30 this.fallbackKeyBackupServices
= fallbackKeyBackupServices
;
31 this.secureValueRecoveryV1
= secureValueRecoveryV1
;
32 this.secureValueRecoveryV2
= secureValueRecoveryV2
;
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();
52 throw new AssertionError("Unexpected response");
56 public void migrateRegistrationLockPin(String pin
, MasterKey masterKey
) throws IOException
{
57 setRegistrationLockPin(pin
, masterKey
);
59 for (final var keyBackupService
: fallbackKeyBackupServices
) {
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());
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();
82 throw new AssertionError("Unexpected response");
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
;
97 var svr2Credentials
= e
.getSvr2Credentials();
98 if (svr2Credentials
!= null) {
99 return getRegistrationLockData(secureValueRecoveryV2
, svr2Credentials
, pin
);
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
);
110 if (restoreResponse
instanceof SecureValueRecovery
.RestoreResponse
.Success 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.");
122 throw new AssertionError("Unexpected response: " + restoreResponse
.getClass().getSimpleName());