Skip to content

Commit

Permalink
RCF-248: Enabled cacerts sync and trust validation (#228)
Browse files Browse the repository at this point in the history
* RCF-226: Changed consent screen fetch logic

Signed-off-by: Himaja Dhanyamraju <Dhanyamraju.Himaja2@mindtree.com>

* RCF-226: Changed decryption logic

Signed-off-by: Himaja Dhanyamraju <Dhanyamraju.Himaja2@mindtree.com>

* Removed unused code

Signed-off-by: Himaja Dhanyamraju <Dhanyamraju.Himaja2@mindtree.com>

* Removed logs

Signed-off-by: Himaja Dhanyamraju <Dhanyamraju.Himaja2@mindtree.com>

* RCF-248: Modified as per review comments

Signed-off-by: Himaja Dhanyamraju <Dhanyamraju.Himaja2@mindtree.com>

* RCF-248: Enabled cacerts sync and trust validation

Signed-off-by: HimajaDhanyamraju2 <dhanyamraju.himaja2@mindtree.com>

* Modified CertificateManagerUtil

Signed-off-by: HimajaDhanyamraju2 <dhanyamraju.himaja2@mindtree.com>

---------

Signed-off-by: Himaja Dhanyamraju <Dhanyamraju.Himaja2@mindtree.com>
Signed-off-by: HimajaDhanyamraju2 <dhanyamraju.himaja2@mindtree.com>
  • Loading branch information
HimajaDhanyamraju2 authored Dec 21, 2023
1 parent fb0e732 commit 94b2548
Show file tree
Hide file tree
Showing 18 changed files with 213 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@

import android.content.Context;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.NonNull;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.apache.commons.io.FileUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
Expand All @@ -32,6 +32,8 @@
import io.mosip.registration.clientmanager.BuildConfig;
import io.mosip.registration.clientmanager.constant.RegistrationConstants;
import io.mosip.registration.clientmanager.dto.CenterMachineDto;
import io.mosip.registration.clientmanager.dto.http.CACertificateDto;
import io.mosip.registration.clientmanager.dto.http.CACertificateResponseDto;
import io.mosip.registration.clientmanager.dto.http.CertificateResponse;
import io.mosip.registration.clientmanager.dto.http.ClientSettingDto;
import io.mosip.registration.clientmanager.dto.http.IdSchemaResponse;
Expand Down Expand Up @@ -60,12 +62,15 @@
import io.mosip.registration.clientmanager.spi.JobManagerService;
import io.mosip.registration.clientmanager.spi.SyncRestService;
import io.mosip.registration.clientmanager.util.SyncRestUtil;
import io.mosip.registration.keymanager.dto.CACertificateRequestDto;
import io.mosip.registration.keymanager.dto.CertificateRequestDto;
import io.mosip.registration.keymanager.dto.CryptoRequestDto;
import io.mosip.registration.keymanager.dto.CryptoResponseDto;
import io.mosip.registration.keymanager.exception.KeymanagerServiceException;
import io.mosip.registration.keymanager.spi.CertificateManagerService;
import io.mosip.registration.keymanager.spi.ClientCryptoManagerService;
import io.mosip.registration.keymanager.util.CryptoUtil;
import io.mosip.registration.keymanager.util.KeyManagerErrorCode;
import io.mosip.registration.packetmanager.util.JsonUtils;
import io.mosip.registration_client.model.MasterDataSyncPigeon;
import okhttp3.ResponseBody;
Expand Down Expand Up @@ -627,4 +632,67 @@ private MasterDataSyncPigeon.Sync syncResult(String syncType, int progress, Stri
.setErrorCode(errorCode)
.build();
}

@Override
public void getCaCertsSync(@NonNull MasterDataSyncPigeon.Result<MasterDataSyncPigeon.Sync> result) {
syncCACertificates(result, 0);
}

private void syncCACertificates(@NonNull MasterDataSyncPigeon.Result<MasterDataSyncPigeon.Sync> result, int retryNo) {
Call<ResponseWrapper<CACertificateResponseDto>> call = syncRestService.getCACertificates(null,
BuildConfig.CLIENT_VERSION);
call.enqueue(new Callback<ResponseWrapper<CACertificateResponseDto>>() {
@Override
public void onResponse(Call<ResponseWrapper<CACertificateResponseDto>> call, Response<ResponseWrapper<CACertificateResponseDto>> response) {
if (response.isSuccessful()) {
ServiceError error = SyncRestUtil.getServiceError(response.body());
String errorMessage = error != null ? error.getMessage() : null;
if (errorMessage == null) {
try {
saveCACertificate(response.body().getResponse().getCertificateDTOList());
result.success(syncResult("CACertificatesSync", 6, ""));
return;
} catch (Throwable t) {
Log.e(TAG, "Failed to sync CA certificates", t);
}
}
result.success(syncResult("CACertificatesSync", 6, "ca_certs_sync_failed"));
} else
result.success(syncResult("CACertificatesSync", 6, "ca_certs_sync_failed"));
}
@Override
public void onFailure(Call<ResponseWrapper<CACertificateResponseDto>> call, Throwable t) {
result.success(syncResult("CACertificatesSync", 6, "ca_certs_sync_failed"));
}
});
}

private void saveCACertificate(List<CACertificateDto> caCertificateDtos) {
if (caCertificateDtos != null && !caCertificateDtos.isEmpty()) {
//Data Fix : As createdDateTime is null sometimes
caCertificateDtos.forEach(c -> {
if (c.getCreatedtimes() == null)
c.setCreatedtimes(LocalDateTime.ofEpochSecond(0, 0, ZoneOffset.UTC));
});
caCertificateDtos.sort((CACertificateDto d1, CACertificateDto d2) -> d1.getCreatedtimes().compareTo(d2.getCreatedtimes()));

for (CACertificateDto cert : caCertificateDtos) {
String errorCode = null;
try {
if (cert.getPartnerDomain() != null && cert.getPartnerDomain().equals("DEVICE")) {
CACertificateRequestDto caCertificateRequestDto = new CACertificateRequestDto();
caCertificateRequestDto.setCertificateData(cert.getCertData());
caCertificateRequestDto.setPartnerDomain(cert.getPartnerDomain());
io.mosip.registration.keymanager.dto.CACertificateResponseDto caCertificateResponseDto = certificateManagerService.uploadCACertificate(caCertificateRequestDto);
Log.i(TAG, caCertificateResponseDto.getStatus());
}
} catch (KeymanagerServiceException ex) {
errorCode = ex.getErrorCode();
}

if (errorCode != null && !errorCode.equals(KeyManagerErrorCode.CERTIFICATE_EXIST_ERROR.getErrorCode()))
throw new KeymanagerServiceException(errorCode, errorCode);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,8 @@ JobManagerService provideJobManagerService(SyncJobDefRepository syncJobDefReposi
@Provides
@Singleton
Biometrics095Service provideBiometrics095Service(ObjectMapper objectMapper, AuditManagerService auditManagerService,
GlobalParamRepository globalParamRepository) {
return new Biometrics095Service(appContext, objectMapper, auditManagerService, globalParamRepository);
GlobalParamRepository globalParamRepository, ClientCryptoManagerService clientCryptoManagerService) {
return new Biometrics095Service(appContext, objectMapper, auditManagerService, globalParamRepository, clientCryptoManagerService);
}

@Provides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
import io.mosip.registration.clientmanager.repository.GlobalParamRepository;
import io.mosip.registration.clientmanager.spi.AuditManagerService;
import io.mosip.registration.clientmanager.spi.BiometricsService;
import io.mosip.registration.keymanager.dto.JWTSignatureVerifyRequestDto;
import io.mosip.registration.keymanager.dto.JWTSignatureVerifyResponseDto;
import io.mosip.registration.keymanager.spi.ClientCryptoManagerService;
import io.mosip.registration.keymanager.util.KeyManagerConstant;

import javax.inject.Inject;
import java.io.InputStream;
Expand All @@ -34,13 +38,16 @@ public class Biometrics095Service extends BiometricsService {
private AuditManagerService auditManagerService;
private GlobalParamRepository globalParamRepository;

private ClientCryptoManagerService clientCryptoManagerService;

@Inject
public Biometrics095Service(Context context, ObjectMapper objectMapper,
AuditManagerService auditManagerService, GlobalParamRepository globalParamRepository) {
AuditManagerService auditManagerService, GlobalParamRepository globalParamRepository, ClientCryptoManagerService clientCryptoManagerService) {
this.context = context;
this.objectMapper = objectMapper;
this.auditManagerService = auditManagerService;
this.globalParamRepository = globalParamRepository;
this.clientCryptoManagerService = clientCryptoManagerService;
}

public CaptureRequest getRCaptureRequest(Modality modality, String deviceId, List<String> exceptionAttributes) {
Expand Down Expand Up @@ -212,4 +219,28 @@ public int getAttemptsCount(Modality modality) {
return 0;
}

/**
* Validates JWT response from DeviceInfo and Rcapture responses.
* if the validation fails, throws BiometricsServiceException with below errors
* SBI_INVALID_SIGNATURE
* SBI_CERT_PATH_TRUST_FAILED
* @param signedData
* @param domain
*/
public void validateJWTResponse(final String signedData, final String domain)
throws Exception {
JWTSignatureVerifyRequestDto jwtSignatureVerifyRequestDto = new JWTSignatureVerifyRequestDto();
jwtSignatureVerifyRequestDto.setValidateTrust(true);
jwtSignatureVerifyRequestDto.setDomain(domain);
jwtSignatureVerifyRequestDto.setJwtSignatureData(signedData);

JWTSignatureVerifyResponseDto jwtSignatureVerifyResponseDto = clientCryptoManagerService.jwtVerify(jwtSignatureVerifyRequestDto);
if(!jwtSignatureVerifyResponseDto.isSignatureValid())
throw new BiometricsServiceException(SBIError.SBI_INVALID_SIGNATURE.getErrorCode(), SBIError.SBI_INVALID_SIGNATURE.getErrorMessage());

if (jwtSignatureVerifyRequestDto.getValidateTrust() && !jwtSignatureVerifyResponseDto.getTrustValid().equals(KeyManagerConstant.TRUST_VALID)) {
throw new BiometricsServiceException(SBIError.SBI_CERT_PATH_TRUST_FAILED.getErrorCode(), SBIError.SBI_CERT_PATH_TRUST_FAILED.getErrorMessage());
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ public void manualSync() {
}
});
}, 0);
//syncCACertificates();
syncCACertificates();
} catch (Exception ex) {
Log.e(TAG, "Data Sync failed", ex);
Toast.makeText(context, "Data Sync failed", Toast.LENGTH_LONG).show();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,30 +29,6 @@ public abstract class BiometricsService {
public static final String BIOMETRIC_SEPARATOR = "(?<=\\.)(.*)(?=\\.)";
private static final String DATETIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z'";

/**
* Validates JWT response from DeviceInfo and Rcapture responses.
* if the validation fails, throws BiometricsServiceException with below errors
* SBI_INVALID_SIGNATURE
* SBI_CERT_PATH_TRUST_FAILED
* @param signedData
* @param domain
*/
public void validateJWTResponse(final String signedData, final String domain)
throws BiometricsServiceException {
/*JWTSignatureVerifyRequestDto jwtSignatureVerifyRequestDto = new JWTSignatureVerifyRequestDto();
jwtSignatureVerifyRequestDto.setValidateTrust(true);
jwtSignatureVerifyRequestDto.setDomain(domain);
jwtSignatureVerifyRequestDto.setJwtSignatureData(signedData);
JWTSignatureVerifyResponseDto jwtSignatureVerifyResponseDto = signatureService.jwtVerify(jwtSignatureVerifyRequestDto);
if(!jwtSignatureVerifyResponseDto.isSignatureValid())
throw new DeviceException(MDMError.MDM_INVALID_SIGNATURE.getErrorCode(), MDMError.MDM_INVALID_SIGNATURE.getErrorMessage());
if (jwtSignatureVerifyRequestDto.getValidateTrust() && !jwtSignatureVerifyResponseDto.getTrustValid().equals(SignatureConstant.TRUST_VALID)) {
throw new DeviceException(MDMError.MDM_CERT_PATH_TRUST_FAILED.getErrorCode(), MDMError.MDM_CERT_PATH_TRUST_FAILED.getErrorMessage());
}*/
}

public String getJWTPayLoad(String jwt) throws BiometricsServiceException {
if (jwt == null || jwt.isEmpty()) {
throw new BiometricsServiceException(SBIError.SBI_JWT_INVALID.getErrorCode(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
Expand Down Expand Up @@ -112,8 +113,7 @@ public static boolean isSelfSignedCertificate(X509Certificate x509Cert) {
try {
x509Cert.verify(x509Cert.getPublicKey());
return true;
} catch (CertificateException | NoSuchAlgorithmException | InvalidKeyException | SignatureException
| NoSuchProviderException exp) {
} catch (GeneralSecurityException exp) {
Log.e(TAG, "Ignore this exception, the exception thrown when signature validation failed.");
}
return false;
Expand Down Expand Up @@ -184,4 +184,4 @@ public static String getPEMFormatedData(Object anyObject){
KeyManagerErrorCode.INTERNAL_SERVER_ERROR.getErrorMessage(), ioExp);
}
}
}
}
1 change: 1 addition & 0 deletions lib/l10n/app_ar.arb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"sync_failed": "مزامنة. فشل",
"sync_failed_message": "يرجى الاتصال بمسؤول النظام أو المشرف للحصول على المساعدة.",
"policy_key_sync_failed":"فشل مزامنة مفتاح السياسة",
"ca_certs_sync_failed":"فشلت مزامنة شهادات CA",
"global_params_sync_failed":"فشل مزامنة Params العالمية",
"user_details_sync_failed":"فشل مزامنة تفاصيل المستخدم",
"id_schema_sync_failed":"فشل مزامنة IDSchema",
Expand Down
3 changes: 2 additions & 1 deletion lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,10 @@
"sync_failed": "Sync. Failed",
"sync_failed_message": "Please connect with the system admin or supervisor for help.",
"policy_key_sync_failed":"Policy Key Sync Failed",
"ca_certs_sync_failed":"CA Certificates Sync Failed",
"global_params_sync_failed":"Global Params Sync Failed",
"user_details_sync_failed":"User Details Sync Failed",
"id_schema_sync_failed":"IDSchena Sync Failed",
"id_schema_sync_failed":"IDSchema Sync Failed",
"master_data_sync_failed":"Master Data Sync Failed",
"network_error": "No network found!",
"delete": "DELETE",
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/app_fr.arb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"sync_failed": "Synchro. Échoué",
"sync_failed_message": "Veuillez contacter l'administrateur système ou le superviseur pour obtenir de l'aide.",
"policy_key_sync_failed":"Échec de la synchronisation de la clé de stratégie",
"ca_certs_sync_failed":"Échec de la synchronisation des certificats CA",
"global_params_sync_failed":"Échec de la synchronisation globale des paramètres",
"user_details_sync_failed":"Échec de la synchronisation des détails de l'utilisateur",
"id_schema_sync_failed":"Échec de la synchronisation IDSchema",
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/app_hi.arb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"sync_failed": "सिंक्रनाइज़ेशन असफल",
"sync_failed_message": "कृपया मदद के लिए सिस्टम व्यवस्थापक या पर्यवेक्षक से कनेक्ट करें.",
"policy_key_sync_failed":"नीति कुंजी सिंक्रनाइज़ेशन विफल",
"ca_certs_sync_failed":"सीए प्रमाणपत्र सिंक विफल रहा",
"global_params_sync_failed":"Global Params Sync विफल",
"user_details_sync_failed":"उपयोगकर्ता विवरण सिंक्रनाइज़ेशन विफल रहा",
"id_schema_sync_failed":"IDSchena सिंक्रनाइज़ेशन विफल रहा",
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/app_kn.arb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"sync_failed": "ಸಿಂಕ್ ವಿಫಲವಾಗಿದೆ",
"sync_failed_message": "ಸಹಾಯಕ್ಕಾಗಿ ದಯವಿಟ್ಟು ಸಿಸ್ಟಂ ನಿರ್ವಾಹಕ ಅಥವಾ ಮೇಲ್ವಿಚಾರಕರನ್ನು ಸಂಪರ್ಕಿಸಿ.",
"policy_key_sync_failed":"ನೀತಿ ಕೀಲಿ ಸಿಂಕ್ ವಿಫಲವಾಗಿದೆ",
"ca_certs_sync_failed":"CA ಪ್ರಮಾಣಪತ್ರಗಳ ಸಿಂಕ್ ವಿಫಲವಾಗಿದೆ",
"global_params_sync_failed":"ಜಾಗತಿಕ ಪರಮ್ಸ್ ಸಿಂಕ್ ವಿಫಲವಾಗಿದೆ",
"user_details_sync_failed":"ಬಳಕೆದಾರ ವಿವರಗಳ ಸಿಂಕ್ ವಿಫಲವಾಗಿದೆ",
"id_schema_sync_failed":"IDSchena ಸಿಂಕ್ ವಿಫಲವಾಗಿದೆ",
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/app_ta.arb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"sync_failed": "ஒத்திசைவு தோல்வியுற்றது",
"sync_failed_message": "உதவிக்கு கணினி நிர்வாகி அல்லது மேற்பார்வையாளருடன் இணைக்கவும்.",
"policy_key_sync_failed":"கொள்கை விசை ஒத்திசைவு தோல்வியுற்றது",
"ca_certs_sync_failed":"CA சான்றிதழ்கள் ஒத்திசைவு தோல்வியடைந்தது",
"global_params_sync_failed":"Global Params Sync தோல்வியுற்றது",
"user_details_sync_failed":"பயனர் விவரங்கள் ஒத்திசைவு தோல்வியுற்றது",
"id_schema_sync_failed":"IDSchena Sync Failed",
Expand Down
13 changes: 13 additions & 0 deletions lib/platform_android/sync_response_service_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,17 @@ class SyncResponseServiceImpl implements SyncResponseService {
}
return syncTime;
}

@override
Future<Sync> getCaCertsSync() async {
late Sync syncResponse;
try {
syncResponse = await SyncApi().getCaCertsSync();
} on PlatformException {
debugPrint('CaCerts Api call failed, PlatformException');
} catch (e) {
debugPrint('CaCertsSync has failed! ${e.toString()}');
}
return syncResponse;
}
}
1 change: 1 addition & 0 deletions lib/platform_spi/sync_response_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ abstract class SyncResponseService {
Future<Sync> getUserDetailsSync();
Future<Sync> getIDSchemaSync();
Future<Sync> getMasterDataSync();
Future<Sync> getCaCertsSync();
}
21 changes: 19 additions & 2 deletions lib/provider/sync_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class SyncProvider with ChangeNotifier {
bool _userDetailsSyncSuccess = false;
bool _idSchemaSyncSuccess = false;
bool _masterDataSyncSuccess = false;
bool _cacertsSyncSuccess = false;

String get lastSuccessfulSyncTime => _lastSuccessfulSyncTime;
int get currentSyncProgress => _currentSyncProgress;
Expand All @@ -29,6 +30,8 @@ class SyncProvider with ChangeNotifier {
bool get userDetailsSyncSuccess => _userDetailsSyncSuccess;
bool get idSchemaSyncSuccess => _idSchemaSyncSuccess;
bool get masterDataSyncSuccess => _masterDataSyncSuccess;
bool get cacertsSyncSuccess => _cacertsSyncSuccess;

set isSyncing(bool value) {
_isSyncing = value;
notifyListeners();
Expand Down Expand Up @@ -111,7 +114,7 @@ class SyncProvider with ChangeNotifier {
notifyListeners();
await SyncResponseServiceImpl()
.getPolicyKeySync()
.then((Sync getAutoSync) {
.then((Sync getAutoSync) async {
setCurrentProgressType(getAutoSync.syncType!);
if (getAutoSync.errorCode == "") {
_masterDataSyncSuccess = true;
Expand All @@ -121,6 +124,19 @@ class SyncProvider with ChangeNotifier {
log(AppLocalizations.of(context)!.policy_key_sync_failed);
}
notifyListeners();
await SyncResponseServiceImpl()
.getCaCertsSync()
.then((Sync getAutoSync) {
setCurrentProgressType(getAutoSync.syncType!);
if (getAutoSync.errorCode == "") {
_cacertsSyncSuccess = true;
_currentSyncProgress = getAutoSync.syncProgress!;
notifyListeners();
} else {
log(AppLocalizations.of(context)!.ca_certs_sync_failed);
}
notifyListeners();
});
});
});
});
Expand All @@ -133,7 +149,8 @@ class SyncProvider with ChangeNotifier {
_globalParamsSyncSuccess &&
_masterDataSyncSuccess &&
_userDetailsSyncSuccess &&
_idSchemaSyncSuccess) {
_idSchemaSyncSuccess &&
_cacertsSyncSuccess) {
return true;
} else {
return false;
Expand Down
Loading

0 comments on commit 94b2548

Please sign in to comment.