diff --git a/README.md b/README.md index ce313af..c4ac7a8 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ cd /port/android ``` 3. Execute the command to build the library. ``` -make NDK_HOME= ANDROID_API=21 DEBUG=1 SECURE=1 IPV4=1 TCP=0 PKI=1 DYNAMIC=1 CLOUD=0 JAVA=1 IDD=1 +make NDK_HOME= ANDROID_API=21 DEBUG=1 SECURE=1 IPV4=1 TCP=1 PKI=1 DYNAMIC=1 CLOUD=1 JAVA=1 IDD=1 ``` Once built, the library can be found at: diff --git a/otgc/build.gradle b/otgc/build.gradle index 4e42a43..2b2d269 100644 --- a/otgc/build.gradle +++ b/otgc/build.gradle @@ -30,7 +30,7 @@ android { minSdkVersion 21 targetSdkVersion 28 versionCode 13 - versionName "3.0.0" + versionName "3.1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" compileOptions { diff --git a/otgc/src/main/assets/cloudca.pem b/otgc/src/main/assets/cloudca.pem new file mode 100644 index 0000000..9026902 --- /dev/null +++ b/otgc/src/main/assets/cloudca.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBhDCCASmgAwIBAgIQdAMxveYP9Nb48xe9kRm3ajAKBggqhkjOPQQDAjAxMS8w +LQYDVQQDEyZPQ0YgQ2xvdWQgUHJpdmF0ZSBDZXJ0aWZpY2F0ZXMgUm9vdCBDQTAe +Fw0xOTExMDYxMjAzNTJaFw0yOTExMDMxMjAzNTJaMDExLzAtBgNVBAMTJk9DRiBD +bG91ZCBQcml2YXRlIENlcnRpZmljYXRlcyBSb290IENBMFkwEwYHKoZIzj0CAQYI +KoZIzj0DAQcDQgAEaNJi86t5QlZiLcJ7uRMNlcwIpmFiJf9MOqyz2GGnGVBypU6H +lwZHY2/l5juO/O4EH2s9h3HfcR+nUG2/tFzFEaMjMCEwDgYDVR0PAQH/BAQDAgEG +MA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSQAwRgIhAM7gFe39UJPIjIDE +KrtyPSIGAk0OAO8txhow1BAGV486AiEAqszg1fTfOHdE/pfs8/9ZP5gEVVkexRHZ +JCYVaa2Spbg= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/otgc/src/main/assets/kyrio-ee-cert.pem b/otgc/src/main/assets/kyrio-ee-cert.pem index 9dcb5b9..fca60cb 100644 --- a/otgc/src/main/assets/kyrio-ee-cert.pem +++ b/otgc/src/main/assets/kyrio-ee-cert.pem @@ -1,24 +1,24 @@ -----BEGIN CERTIFICATE----- -MIIEEzCCA7mgAwIBAgIJAI0K+3tTsk07MAoGCCqGSM49BAMCMFsxDDAKBgNVBAoM +MIID/jCCA6OgAwIBAgIJAI0K+3tTslNtMAoGCCqGSM49BAMCMFsxDDAKBgNVBAoM A09DRjEiMCAGA1UECwwZS3lyaW8gVGVzdCBJbmZyYXN0cnVjdHVyZTEnMCUGA1UE -AwweS3lyaW8gVEVTVCBJbnRlcm1lZGlhdGUgQ0EwMDAyMB4XDTE5MTEyODEzMzYw -OVoXDTE5MTIyODEzMzYwOVowYTEMMAoGA1UECgwDT0NGMSIwIAYDVQQLDBlLeXJp -byBUZXN0IEluZnJhc3RydWN0dXJlMS0wKwYDVQQDDCQxZTFiZWJmYi04ZjAzLTQ3 -ODUtNWZhNy0xYjcwNGU2NTQzNjAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQS -rNS0ha8XBiRD+Q7nL+R3uX7f5FPgQO75Wh9PqaiVLhMFewF/Yrbr+KhCdj8e6MNz -WGDbVtMVc59RBHyvgzbho4ICXjCCAlowCQYDVR0TBAIwADAOBgNVHQ8BAf8EBAMC -A4gwKQYDVR0lBCIwIAYIKwYBBQUHAwIGCCsGAQUFBwMBBgorBgEEAYLefAEGMB0G -A1UdDgQWBBR1GbdeJoLZj6iMx9ZDNEv+aoECrjAfBgNVHSMEGDAWgBQZc2oEGgsH -cE9TeVM2h/wMunyuCzCBlgYIKwYBBQUHAQEEgYkwgYYwXQYIKwYBBQUHMAKGUWh0 -dHA6Ly90ZXN0cGtpLmt5cmlvLmNvbS9vY2YvY2FjZXJ0cy9CQkU2NEY5QTdFRTM3 -RDI5QTA1RTRCQjc3NTk1RjMwOEJFNDFFQjA3LmNydDAlBggrBgEFBQcwAYYZaHR0 -cDovL3Rlc3RvY3NwLmt5cmlvLmNvbTBfBgNVHR8EWDBWMFSgUqBQhk5odHRwOi8v -dGVzdHBraS5reXJpby5jb20vb2NmL2NybHMvQkJFNjRGOUE3RUUzN0QyOUEwNUU0 -QkI3NzU5NUYzMDhCRTQxRUIwNy5jcmwwGAYDVR0gBBEwDzANBgsrBgEEAYORVgAB -AjBgBgorBgEEAYORVgEABFIwUDAJAgECAgEAAgEAMDYMGTEuMy42LjEuNC4xLjUx -NDE0LjAuMC4xLjAMGTEuMy42LjEuNC4xLjUxNDE0LjAuMC4yLjAMBE9UR0MMBURF -S1JBMCoGCisGAQQBg5FWAQEEHDAaBgsrBgEEAYORVgEBAAYLKwYBBAGDkVYBAQEw -MAYKKwYBBAGDkVYBAgQiMCAMDjEuMy42LjEuNC4xLjcxDAlEaXNjb3ZlcnkMAzEu -MDAKBggqhkjOPQQDAgNIADBFAiAP9ttApmZfcFoipNra7ZqFa1kdD7JxmD84fuMH -XXyTBgIhAIIrpiVkOxAQqTlfDpJZk3F8byz/x2c9xpNeQEZTllMc +AwweS3lyaW8gVEVTVCBJbnRlcm1lZGlhdGUgQ0EwMDAyMB4XDTIxMTAwNjA5Mjcz +NVoXDTIxMTEwNTA5MjczNVowRjEMMAoGA1UECgwDT0NGMSIwIAYDVQQLDBlLeXJp +byBUZXN0IEluZnJhc3RydWN0dXJlMRIwEAYDVQQDDAlwa2lfY2VydHMwWTATBgcq +hkjOPQIBBggqhkjOPQMBBwNCAARPhgvrI3VG5KDAy4QQnPndI4en9yoIIQWO9PY7 +gT60mfwIElH2PbeEFJwS+6RmNtSnGeo1Vb2UQx3bgpEgULMBo4ICYzCCAl8wCQYD +VR0TBAIwADAOBgNVHQ8BAf8EBAMCA4gwKQYDVR0lBCIwIAYIKwYBBQUHAwIGCCsG +AQUFBwMBBgorBgEEAYLefAEGMB0GA1UdDgQWBBRDsU3IcO3AHYvyWp0NjWm4ob6a +uzAfBgNVHSMEGDAWgBQZc2oEGgsHcE9TeVM2h/wMunyuCzCBlgYIKwYBBQUHAQEE +gYkwgYYwXQYIKwYBBQUHMAKGUWh0dHA6Ly90ZXN0cGtpLmt5cmlvLmNvbS9vY2Yv +Y2FjZXJ0cy9CQkU2NEY5QTdFRTM3RDI5QTA1RTRCQjc3NTk1RjMwOEJFNDFFQjA3 +LmNydDAlBggrBgEFBQcwAYYZaHR0cDovL3Rlc3RvY3NwLmt5cmlvLmNvbTBfBgNV +HR8EWDBWMFSgUqBQhk5odHRwOi8vdGVzdHBraS5reXJpby5jb20vb2NmL2NybHMv +QkJFNjRGOUE3RUUzN0QyOUEwNUU0QkI3NzU5NUYzMDhCRTQxRUIwNy5jcmwwGAYD +VR0gBBEwDzANBgsrBgEEAYORVgABAjBlBgorBgEEAYORVgEABFcwVTAJAgECAgEA +AgEAMDYMGTEuMy42LjEuNC4xLjUxNDE0LjAuMC4xLjAMGTEuMy42LjEuNC4xLjUx +NDE0LjAuMC4yLjAMC0RldmljZU5hbWUxDANPQ0YwKgYKKwYBBAGDkVYBAQQcMBoG +CysGAQQBg5FWAQEABgsrBgEEAYORVgEBATAwBgorBgEEAYORVgECBCIwIAwOMS4z +LjYuMS40LjEuNzEMCURpc2NvdmVyeQwDMS4wMAoGCCqGSM49BAMCA0kAMEYCIQCn +bJELNfcNIMF/o7fD1GMVo5bipfBgKe45TkUTFxHqJAIhAJocMkb89i5l1htY6Zxh +6IrWOduBtpU7LaNfhLyWQZA0 -----END CERTIFICATE----- diff --git a/otgc/src/main/assets/kyrio-ee-key.pem b/otgc/src/main/assets/kyrio-ee-key.pem index 80c8b7a..670033f 100644 --- a/otgc/src/main/assets/kyrio-ee-key.pem +++ b/otgc/src/main/assets/kyrio-ee-key.pem @@ -2,7 +2,7 @@ BggqhkjOPQMBBw== -----END EC PARAMETERS----- -----BEGIN EC PRIVATE KEY----- -MHcCAQEEIDFeXNSayEnCQIlEjbV+4vGKeqRAmjnspnA8ICW0FnAwoAoGCCqGSM49 -AwEHoUQDQgAEEqzUtIWvFwYkQ/kO5y/kd7l+3+RT4EDu+VofT6molS4TBXsBf2K2 -6/ioQnY/HujDc1hg21bTFXOfUQR8r4M24Q== +MHcCAQEEIDKAzV1vjeRU1ET9HVHcQVTjr6ClMoGt1Yhjrky2MYyaoAoGCCqGSM49 +AwEHoUQDQgAET4YL6yN1RuSgwMuEEJz53SOHp/cqCCEFjvT2O4E+tJn8CBJR9j23 +hBScEvukZjbUpxnqNVW9lEMd24KRIFCzAQ== -----END EC PRIVATE KEY----- diff --git a/otgc/src/main/java/org/openconnectivity/otgc/data/repository/CmsRepository.java b/otgc/src/main/java/org/openconnectivity/otgc/data/repository/CmsRepository.java index 1170bbd..4f33e30 100644 --- a/otgc/src/main/java/org/openconnectivity/otgc/data/repository/CmsRepository.java +++ b/otgc/src/main/java/org/openconnectivity/otgc/data/repository/CmsRepository.java @@ -142,6 +142,26 @@ public Completable provisionRoleCertificate(String deviceId, String roleId, Stri }); } + public Completable provisionTrustAnchor(byte[] certificate, String sid, String deviceId) { + return Completable.create(emitter -> { + OCUuid di = OCUuidUtil.stringToUuid(deviceId); + + OCObtStatusHandler handler = (int status) -> { + if (status >= 0) { + Timber.d("Provision trust anchor succeeded"); + emitter.onComplete(); + } else { + emitter.onError(new Exception("Provision trust anchor error")); + } + }; + + int ret = OCObt.provisionTrustAnchor(certificate, sid, di, handler); + if (ret < 0) { + emitter.onError(new Exception("Provision trust anchor error")); + } + }); + } + public Completable provisionPairwiseCredential(String clientId, String serverId) { return Completable.create(emitter -> { OCUuid cliendDi = OCUuidUtil.stringToUuid(clientId); @@ -250,4 +270,31 @@ public Completable removeTrustAnchor(long credid) { } }); } + + public Completable registerDeviceCloud(String deviceId, String deviceURL, String authProvider, String cloudUrl, String cloudUuid, String accessToken) { + return Completable.create(emitter -> { + OCCloudContext ctx = OCCloud.getContext(0); + + OCUuid uuid = OCUuidUtil.stringToUuid(deviceId); + + OCResponseHandler handler = (OCClientResponse response) -> { + if (response.getCode() == OCStatus.OC_STATUS_CHANGED) { + Timber.d("Register device on cloud success"); + emitter.onComplete(); + } else if (response.getCode() == OCStatus.OC_STATUS_CREATED) { + Timber.d("Register device on cloud success"); + emitter.onComplete(); + } else { + String error = "Register device on cloud error"; + Timber.e(error + ": " + response.getCode()); + emitter.onError(new Exception(error)); + } + }; + + if (ctx != null) { + OCObt.UpdateCloudConfDevice(uuid, deviceURL, accessToken, authProvider, cloudUrl, cloudUuid, handler); + } + emitter.onComplete(); + }); + } } diff --git a/otgc/src/main/java/org/openconnectivity/otgc/data/repository/IotivityRepository.java b/otgc/src/main/java/org/openconnectivity/otgc/data/repository/IotivityRepository.java index d263954..d180cb6 100644 --- a/otgc/src/main/java/org/openconnectivity/otgc/data/repository/IotivityRepository.java +++ b/otgc/src/main/java/org/openconnectivity/otgc/data/repository/IotivityRepository.java @@ -353,6 +353,22 @@ public Observable scanOwnedByOtherDevices() { .filter(device -> !device.getDeviceId().equals(getDeviceId().blockingGet())); } + public Single getEndpoint(Device device) { + return Single.create(emitter -> { + String endpoint = device.getIpv6Host() != null ? device.getIpv6Host() : device.getIpv6TcpHost(); + if (endpoint == null) { + endpoint = device.getIpv4Host() != null ? device.getIpv4Host() : device.getIpv4TcpHost(); + if (endpoint == null) { + endpoint = device.getIpv6SecureHost() != null ? device.getIpv6SecureHost() : device.getIpv6TcpSecureHost(); + if (endpoint == null) { + endpoint = device.getIpv4SecureHost() != null ? device.getIpv4SecureHost() : device.getIpv4TcpSecureHost(); + } + } + } + emitter.onSuccess(endpoint); + }); + } + public Single getNonSecureEndpoint(Device device) { return Single.create(emitter -> { String endpoint = device.getIpv6Host() != null ? device.getIpv6Host() : device.getIpv6TcpHost(); diff --git a/otgc/src/main/java/org/openconnectivity/otgc/domain/model/resource/secure/cred/OcCredential.java b/otgc/src/main/java/org/openconnectivity/otgc/domain/model/resource/secure/cred/OcCredential.java index cd25715..55cb2b3 100644 --- a/otgc/src/main/java/org/openconnectivity/otgc/domain/model/resource/secure/cred/OcCredential.java +++ b/otgc/src/main/java/org/openconnectivity/otgc/domain/model/resource/secure/cred/OcCredential.java @@ -134,9 +134,13 @@ public void parseOCRepresentation(OCCred cred) { this.setPublicData(publicData); } /* privatedata */ + // Reading Private Data fails sometimes on Android. As it not used, it has been commented + /* OcCredPrivateData privateData = new OcCredPrivateData(); privateData.parseOCRepresentation(cred.getPrivateData()); this.setPrivateData(privateData); + */ + /* roleid */ if (cred.getRole() != null) { OcCredRole roleid = new OcCredRole(); diff --git a/otgc/src/main/java/org/openconnectivity/otgc/domain/model/resource/secure/doxm/OcDoxm.java b/otgc/src/main/java/org/openconnectivity/otgc/domain/model/resource/secure/doxm/OcDoxm.java index a4786b2..f2107f8 100644 --- a/otgc/src/main/java/org/openconnectivity/otgc/domain/model/resource/secure/doxm/OcDoxm.java +++ b/otgc/src/main/java/org/openconnectivity/otgc/domain/model/resource/secure/doxm/OcDoxm.java @@ -130,10 +130,10 @@ public void parseOCRepresentation(OCRepresentation rep) { this.setRowneruuid(rowneruuid); /* rt */ String[] resourceTypes = OCRep.getStringArray(rep, OcfResourceAttributeKey.RESOURCE_TYPES_KEY); - this.setResourceTypes(Arrays.asList(resourceTypes)); + this.setResourceTypes(resourceTypes != null ? Arrays.asList(resourceTypes) : null); /* if */ String[] interfaces = OCRep.getStringArray(rep, OcfResourceAttributeKey.INTERFACES_KEY); - this.setResourceTypes(Arrays.asList(interfaces)); + this.setInterfaces(interfaces != null ? Arrays.asList(interfaces) : null); } public CborEncoder parseToCbor() { diff --git a/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/GetDeviceInfoUseCase.java b/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/GetDeviceInfoUseCase.java index 42d18f0..d801295 100644 --- a/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/GetDeviceInfoUseCase.java +++ b/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/GetDeviceInfoUseCase.java @@ -52,7 +52,7 @@ public GetDeviceInfoUseCase(IotivityRepository iotivityRepository, } public Single execute(Device device) { - return iotivityRepository.getNonSecureEndpoint(device) + return iotivityRepository.getEndpoint(device) .flatMap(iotivityRepository::getDeviceInfo) .delay(preferencesRepository.getRequestsDelay(), TimeUnit.SECONDS, schedulersFacade.ui()); } diff --git a/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/GetDeviceRoleUseCase.java b/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/GetDeviceRoleUseCase.java index e1c2608..36b6ef5 100644 --- a/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/GetDeviceRoleUseCase.java +++ b/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/GetDeviceRoleUseCase.java @@ -55,7 +55,7 @@ public GetDeviceRoleUseCase(IotivityRepository iotivityRepository, } public Single execute(Device device) { - return iotivityRepository.getNonSecureEndpoint(device) + return iotivityRepository.getEndpoint(device) .flatMap(endpoint -> iotivityRepository.findResources(endpoint) .timeout(iotivityRepository.getDiscoveryTimeout() + 5, TimeUnit.SECONDS) diff --git a/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/GetOTMethodsUseCase.java b/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/GetOTMethodsUseCase.java index dba03de..9a8bf40 100644 --- a/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/GetOTMethodsUseCase.java +++ b/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/GetOTMethodsUseCase.java @@ -45,7 +45,7 @@ public GetOTMethodsUseCase(IotivityRepository iotivityRepository, } public Single> execute(Device device) { - return iotivityRepository.getNonSecureEndpoint(device) + return iotivityRepository.getEndpoint(device) .flatMap(endpoint -> doxsRepository.retrieveOTMethods(endpoint) .map(doxm -> doxm.getOxms())); diff --git a/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/InitializeIotivityUseCase.java b/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/InitializeIotivityUseCase.java index 65e8ce4..652ca2a 100644 --- a/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/InitializeIotivityUseCase.java +++ b/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/InitializeIotivityUseCase.java @@ -92,37 +92,40 @@ private void factoryResetHandler(long device) throws Exception { /* Current date */ Date date = new Date(); - /* Kyrio end-entity cert */ - InputStream inputStream = context.getAssets().open(OtgcConstant.KYRIO_EE_CERTIFICATE); - X509Certificate eeCert = ioRepository.getFileAsX509Certificate(inputStream).blockingGet(); - if (date.after(eeCert.getNotBefore()) && date.before(eeCert.getNotAfter())) { - byte[] kyrioEeCertificate = ioRepository.getBytesFromFile(OtgcConstant.KYRIO_EE_CERTIFICATE).blockingGet(); - /* private key of Kyrio end-entity cert */ - byte[] kyrioEeKey = ioRepository.getBytesFromFile(OtgcConstant.KYRIO_EE_KEY).blockingGet(); - int credid = OCPki.addMfgCert(device, kyrioEeCertificate, kyrioEeKey); - if (credid == -1) { - throw new Exception("Add identity certificate error"); - } + // End-entity certs only loaded when using Client Mode + if (settingRepository.getMode().equals(OtgcMode.CLIENT)) { + /* Kyrio end-entity cert */ + InputStream inputStream = context.getAssets().open(OtgcConstant.KYRIO_EE_CERTIFICATE); + X509Certificate eeCert = ioRepository.getFileAsX509Certificate(inputStream).blockingGet(); + if (date.after(eeCert.getNotBefore()) && date.before(eeCert.getNotAfter())) { + byte[] kyrioEeCertificate = ioRepository.getBytesFromFile(OtgcConstant.KYRIO_EE_CERTIFICATE).blockingGet(); + /* private key of Kyrio end-entity cert */ + byte[] kyrioEeKey = ioRepository.getBytesFromFile(OtgcConstant.KYRIO_EE_KEY).blockingGet(); + int credid = OCPki.addMfgCert(device, kyrioEeCertificate, kyrioEeKey); + if (credid == -1) { + throw new Exception("Add identity certificate error"); + } - /* Kyrio intermediate cert */ - inputStream = context.getAssets().open(OtgcConstant.KYRIO_SUBCA_CERTIFICATE); - X509Certificate subCaCert = ioRepository.getFileAsX509Certificate(inputStream).blockingGet(); - if (date.after(subCaCert.getNotBefore()) && date.before(subCaCert.getNotAfter())) { - byte[] kyrioSubcaCertificate = ioRepository.getBytesFromFile(OtgcConstant.KYRIO_SUBCA_CERTIFICATE).blockingGet(); - if (OCPki.addMfgIntermediateCert(device, credid, kyrioSubcaCertificate) == -1) { - throw new Exception("Add intermediate certificate error"); + /* Kyrio intermediate cert */ + inputStream = context.getAssets().open(OtgcConstant.KYRIO_SUBCA_CERTIFICATE); + X509Certificate subCaCert = ioRepository.getFileAsX509Certificate(inputStream).blockingGet(); + if (date.after(subCaCert.getNotBefore()) && date.before(subCaCert.getNotAfter())) { + byte[] kyrioSubcaCertificate = ioRepository.getBytesFromFile(OtgcConstant.KYRIO_SUBCA_CERTIFICATE).blockingGet(); + if (OCPki.addMfgIntermediateCert(device, credid, kyrioSubcaCertificate) == -1) { + throw new Exception("Add intermediate certificate error"); + } + } else { + this.displayNotValidCertificateHandler.handler("Kyrio intermediate certificate is not valid"); } } else { - this.displayNotValidCertificateHandler.handler("Kyrio intermediate certificate is not valid"); + this.displayNotValidCertificateHandler.handler("Kyrio end entity certificate is not valid"); } - } else { - this.displayNotValidCertificateHandler.handler("Kyrio end entity certificate is not valid"); } /* Kyrio root cert */ - inputStream = context.getAssets().open(OtgcConstant.KYRIO_ROOT_CERTIFICATE); - X509Certificate caCert = ioRepository.getFileAsX509Certificate(inputStream).blockingGet(); - if (date.after(caCert.getNotBefore()) && date.before(caCert.getNotAfter())) { + InputStream inputStream = context.getAssets().open(OtgcConstant.KYRIO_ROOT_CERTIFICATE); + X509Certificate caCert1 = ioRepository.getFileAsX509Certificate(inputStream).blockingGet(); + if (date.after(caCert1.getNotBefore()) && date.before(caCert1.getNotAfter())) { byte[] kyrioRootcaCertificate = ioRepository.getBytesFromFile(OtgcConstant.KYRIO_ROOT_CERTIFICATE).blockingGet(); if (OCPki.addMfgTrustAnchor(device, kyrioRootcaCertificate) == -1) { throw new Exception("Add root certificate error"); @@ -133,8 +136,8 @@ private void factoryResetHandler(long device) throws Exception { /* EonTi root cert */ inputStream = context.getAssets().open(OtgcConstant.EONTI_ROOT_CERTIFICATE); - caCert = ioRepository.getFileAsX509Certificate(inputStream).blockingGet(); - if (date.after(caCert.getNotBefore()) && date.before(caCert.getNotAfter())) { + X509Certificate caCert2 = ioRepository.getFileAsX509Certificate(inputStream).blockingGet(); + if (date.after(caCert2.getNotBefore()) && date.before(caCert2.getNotAfter())) { byte[] eontiRootcaCertificate = ioRepository.getBytesFromFile(OtgcConstant.EONTI_ROOT_CERTIFICATE).blockingGet(); if (OCPki.addMfgTrustAnchor(device, eontiRootcaCertificate) == -1) { throw new Exception("Add root certificate error"); @@ -143,6 +146,18 @@ private void factoryResetHandler(long device) throws Exception { this.displayNotValidCertificateHandler.handler("EonTi root certificate is not valid"); } + /* CloudCA root cert */ + inputStream = context.getAssets().open(OtgcConstant.CLOUD_ROOT_CERTIFICATE); + X509Certificate cloudCert = ioRepository.getFileAsX509Certificate(inputStream).blockingGet(); + if (date.after(cloudCert.getNotBefore()) && date.before(cloudCert.getNotAfter())) { + byte[] cloudRootcaCertificate = ioRepository.getBytesFromFile(OtgcConstant.CLOUD_ROOT_CERTIFICATE).blockingGet(); + if (OCPki.addMfgTrustAnchor(device, cloudRootcaCertificate) == -1) { + throw new Exception("Add root certificate error"); + } + } else { + this.displayNotValidCertificateHandler.handler("Cloud CA root certificate is not valid"); + } + OCObt.shutdown(); } } diff --git a/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/ResetClientModeUseCase.java b/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/ResetClientModeUseCase.java index 9dc5ad7..0466386 100644 --- a/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/ResetClientModeUseCase.java +++ b/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/ResetClientModeUseCase.java @@ -21,7 +21,9 @@ public ResetClientModeUseCase(ProvisioningRepository provisioningRepository, } public Completable execute() { - return provisioningRepository.resetSvrDb() - .andThen(Completable.fromAction(() -> preferencesRepository.setMode(OtgcMode.CLIENT))); + //return provisioningRepository.resetSvrDb() + // .andThen(Completable.fromAction(() -> preferencesRepository.setMode(OtgcMode.CLIENT))); + return Completable.fromAction(() -> preferencesRepository.setMode(OtgcMode.CLIENT)) + .andThen (provisioningRepository.resetSvrDb()); } } diff --git a/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/ResetObtModeUseCase.java b/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/ResetObtModeUseCase.java index 2e175dc..c093fa9 100644 --- a/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/ResetObtModeUseCase.java +++ b/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/ResetObtModeUseCase.java @@ -34,8 +34,8 @@ public Completable execute() { return iotivityRepository.scanOwnedDevices() .flatMapCompletable(device -> doxsRepository.resetDevice(device.getDeviceId())) .delay(preferencesRepository.getRequestsDelay(), TimeUnit.SECONDS) + .andThen(Completable.fromAction(() -> preferencesRepository.setMode(OtgcMode.OBT))) .andThen(provisioningRepository.resetSvrDb()) - .andThen(provisioningRepository.doSelfOwnership()) - .andThen(Completable.fromAction(() -> preferencesRepository.setMode(OtgcMode.OBT))); + .andThen(provisioningRepository.doSelfOwnership()); } } diff --git a/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/RetrieveVerticalResourcesUseCase.java b/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/RetrieveVerticalResourcesUseCase.java index 8745427..64b7c80 100644 --- a/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/RetrieveVerticalResourcesUseCase.java +++ b/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/RetrieveVerticalResourcesUseCase.java @@ -40,7 +40,7 @@ public RetrieveVerticalResourcesUseCase(IotivityRepository iotivityRepository) { } public Single> execute(Device device) { - return iotivityRepository.getNonSecureEndpoint(device) + return iotivityRepository.getEndpoint(device) .flatMap(iotivityRepository::findResources) .map(ocRes -> { List verticalResources = new ArrayList<>(); diff --git a/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/client/GetPlatformInfoUseCase.java b/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/client/GetPlatformInfoUseCase.java index 8443634..7a7c48f 100644 --- a/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/client/GetPlatformInfoUseCase.java +++ b/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/client/GetPlatformInfoUseCase.java @@ -39,7 +39,7 @@ public GetPlatformInfoUseCase(IotivityRepository iotivityRepository) { } public Single execute(Device device) { - return iotivityRepository.getNonSecureEndpoint(device) + return iotivityRepository.getEndpoint(device) .flatMap(iotivityRepository::getPlatformInfo); } } diff --git a/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/client/IntrospectUseCase.java b/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/client/IntrospectUseCase.java index 91ff23b..231144c 100644 --- a/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/client/IntrospectUseCase.java +++ b/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/client/IntrospectUseCase.java @@ -48,7 +48,7 @@ public IntrospectUseCase(IotivityRepository iotivityRepository) { } public Single execute(Device device) { - return iotivityRepository.getNonSecureEndpoint(device) + return iotivityRepository.getEndpoint(device) .flatMap(endpoint -> iotivityRepository.findResource(endpoint, OcfResourceType.INTROSPECTION)) .flatMap(res -> { OcResource introspectionResource = res.getResourceList().get(0); diff --git a/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/cloud/RegisterDeviceCloudUseCase.java b/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/cloud/RegisterDeviceCloudUseCase.java new file mode 100644 index 0000000..9e9ea12 --- /dev/null +++ b/otgc/src/main/java/org/openconnectivity/otgc/domain/usecase/cloud/RegisterDeviceCloudUseCase.java @@ -0,0 +1,55 @@ +package org.openconnectivity.otgc.domain.usecase.cloud; + +import io.reactivex.Completable; +import org.iotivity.OCCredUsage; +import org.iotivity.OCCredUtil; +import org.openconnectivity.otgc.data.repository.*; +import org.openconnectivity.otgc.domain.model.devicelist.Device; +import org.openconnectivity.otgc.domain.model.resource.secure.cred.OcCredential; +import org.openconnectivity.otgc.domain.model.resource.secure.cred.OcCredentials; +import org.openconnectivity.otgc.utils.rx.SchedulersFacade; +import org.openconnectivity.otgc.domain.model.resource.cloud.OcCloudConfiguration; + +import javax.inject.Inject; +import java.util.Arrays; + +public class RegisterDeviceCloudUseCase { + + private final IotivityRepository iotivityRepository; + private final CloudRepository cloudRepository; + private final AmsRepository amsRepository; + private final CmsRepository cmsRepository; + + @Inject + public RegisterDeviceCloudUseCase(IotivityRepository iotivityRepository, + AmsRepository amsRepository, + CloudRepository cloudRepository, + CmsRepository cmsRepository) { + this.iotivityRepository = iotivityRepository; + this.amsRepository = amsRepository; + this.cloudRepository = cloudRepository; + this.cmsRepository = cmsRepository; + } + + public Completable execute(Device deviceToRegister, String accessToken) { + + //int delay = Integer.parseInt(settingRepository.get(SettingRepository.REQUESTS_DELAY_KEY, SettingRepository.REQUESTS_DELAY_DEFAULT_VALUE)); + + OcCloudConfiguration configuration = cloudRepository.retrieveCloudConfiguration().blockingGet(); + + + OcCredentials creds = cmsRepository.retrieveOwnCredentials().blockingGet(); + for(OcCredential cred : creds.getCredList()) { + if (cred.getCredusage() != null && !cred.getCredusage().isEmpty() + && (OCCredUtil.parseCredUsage(cred.getCredusage()) == OCCredUsage.OC_CREDUSAGE_MFG_TRUSTCA + || OCCredUtil.parseCredUsage(cred.getCredusage()) == OCCredUsage.OC_CREDUSAGE_TRUSTCA)) { + byte[] pem = cred.getPublicData().getPemData().getBytes(); + cmsRepository.provisionTrustAnchor(pem, configuration.getCloudUuid(), deviceToRegister.getDeviceId()).blockingGet(); + } + } + + return amsRepository.provisionConntypeAce(deviceToRegister.getDeviceId(), true, Arrays.asList("/CoapCloudConfResURI"), 6). + andThen(cmsRepository.registerDeviceCloud(deviceToRegister.getDeviceId(), "/CoapCloudConfResURI", configuration.getAuthProvider(), configuration.getCloudUrl(), + configuration.getCloudUuid(), accessToken)); + } +} diff --git a/otgc/src/main/java/org/openconnectivity/otgc/utils/constant/OtgcConstant.java b/otgc/src/main/java/org/openconnectivity/otgc/utils/constant/OtgcConstant.java index 636f13a..7dc0ea6 100644 --- a/otgc/src/main/java/org/openconnectivity/otgc/utils/constant/OtgcConstant.java +++ b/otgc/src/main/java/org/openconnectivity/otgc/utils/constant/OtgcConstant.java @@ -44,4 +44,5 @@ private OtgcConstant() { public static String KYRIO_SUBCA_CERTIFICATE = "kyrio-subca-cert.pem"; public static String KYRIO_EE_CERTIFICATE = "kyrio-ee-cert.pem"; public static String KYRIO_EE_KEY = "kyrio-ee-key.pem"; + public static String CLOUD_ROOT_CERTIFICATE = "cloudca.pem"; } diff --git a/otgc/src/main/java/org/openconnectivity/otgc/view/devicelist/DeviceListActivity.java b/otgc/src/main/java/org/openconnectivity/otgc/view/devicelist/DeviceListActivity.java index f681a3a..362ba2a 100644 --- a/otgc/src/main/java/org/openconnectivity/otgc/view/devicelist/DeviceListActivity.java +++ b/otgc/src/main/java/org/openconnectivity/otgc/view/devicelist/DeviceListActivity.java @@ -215,10 +215,10 @@ public boolean onOptionsItemSelected(MenuItem item) { } break; case R.id.menu_item_obt_mode: - showConfirmSetMode(OtgcMode.OBT, false); + showConfirmSetMode(OtgcMode.OBT, true); break; case R.id.menu_item_client_mode: - showConfirmSetMode(OtgcMode.CLIENT, false); + showConfirmSetMode(OtgcMode.CLIENT, true); break; case R.id.menu_item_trust_anchor: onTrustAnchorManagement(); diff --git a/otgc/src/main/java/org/openconnectivity/otgc/view/devicelist/DoxsFragment.java b/otgc/src/main/java/org/openconnectivity/otgc/view/devicelist/DoxsFragment.java index 17a5671..d0adf76 100644 --- a/otgc/src/main/java/org/openconnectivity/otgc/view/devicelist/DoxsFragment.java +++ b/otgc/src/main/java/org/openconnectivity/otgc/view/devicelist/DoxsFragment.java @@ -262,6 +262,12 @@ private RecyclerView.Adapter getAdapter() { positionWifiEasySetupItem = position; mViewModel.scanWifiNetworks(); break; + case R.id.menu_item_register_device_cloud: + showSetAccessTokenDialog( + position, mAdapter.mDataset.get(position) + + ); + break; case R.id.button_offboard: positionBeingUpdated = position; mViewModel.offboard(mAdapter.mDataset.get(position)); @@ -696,4 +702,23 @@ private void showSetDeviceNameDialog(int position, String deviceId, String curre dialog.setView(input, (int)(16*dpi), (int)(16*dpi), (int)(16*dpi), (int)(16*dpi)); dialog.show(); } + + private void showSetAccessTokenDialog(int position, Device deviceToRegister) { + float dpi = getContext().getResources().getDisplayMetrics().density; + final TextInputEditText input = new TextInputEditText(getActivity()); + input.setText(""); + input.setSelectAllOnFocus(true); + input.requestFocus(); + AlertDialog dialog = (new AlertDialog.Builder(getActivity())) + .setTitle(getString(R.string.devices_dialog_set_access_token_title)) + .setPositiveButton(getString(R.string.devices_dialog_set_access_token_yes_option), (dialogInterface, which) -> { + mViewModel.registerDeviceCloud(deviceToRegister, input.getText().toString()); + }) + .setNegativeButton( + getString(R.string.devices_dialog_set_access_token_no_option), + null) + .create(); + dialog.setView(input, (int)(16*dpi), (int)(16*dpi), (int)(16*dpi), (int)(16*dpi)); + dialog.show(); + } } diff --git a/otgc/src/main/java/org/openconnectivity/otgc/view/trustanchor/CertificateActivity.java b/otgc/src/main/java/org/openconnectivity/otgc/view/trustanchor/CertificateActivity.java index d312b2d..4d30c07 100644 --- a/otgc/src/main/java/org/openconnectivity/otgc/view/trustanchor/CertificateActivity.java +++ b/otgc/src/main/java/org/openconnectivity/otgc/view/trustanchor/CertificateActivity.java @@ -207,6 +207,11 @@ private void initViewModel() { mViewModel.getError().observe(this, this::handleError); mViewModel.getSuccess().observe(this, this::processSuccess); + + if (mViewModel.isClientMode()) + endEntityRadioButton.setEnabled(true); + else + endEntityRadioButton.setEnabled(false); } private void handleProcessing(@NonNull Boolean isProcessing) { diff --git a/otgc/src/main/java/org/openconnectivity/otgc/viewmodel/CertificateViewModel.java b/otgc/src/main/java/org/openconnectivity/otgc/viewmodel/CertificateViewModel.java index ee53efa..a6424cb 100644 --- a/otgc/src/main/java/org/openconnectivity/otgc/viewmodel/CertificateViewModel.java +++ b/otgc/src/main/java/org/openconnectivity/otgc/viewmodel/CertificateViewModel.java @@ -7,9 +7,12 @@ import org.openconnectivity.otgc.domain.usecase.trustanchor.SaveEndEntityCertificateUseCase; import org.openconnectivity.otgc.domain.usecase.trustanchor.SaveIntermediateCertificateUseCase; import org.openconnectivity.otgc.domain.usecase.trustanchor.StoreTrustAnchorUseCase; +import org.openconnectivity.otgc.utils.constant.OtgcMode; import org.openconnectivity.otgc.utils.rx.SchedulersFacade; import org.openconnectivity.otgc.utils.viewmodel.ViewModelError; import org.openconnectivity.otgc.utils.viewmodel.ViewModelErrorType; +import org.openconnectivity.otgc.utils.constant.OtgcMode; +import org.openconnectivity.otgc.data.repository.PreferencesRepository; import java.io.InputStream; @@ -26,6 +29,7 @@ public class CertificateViewModel extends ViewModel { private final StoreTrustAnchorUseCase storeTrustAnchorUseCase; private final SaveIntermediateCertificateUseCase saveIntermediateCertificateUseCase; private final SaveEndEntityCertificateUseCase saveEndEntityCertificateUseCase; + private final PreferencesRepository settingRepository; private final MutableLiveData mProcessing = new MutableLiveData<>(); private final MutableLiveData mError = new MutableLiveData<>(); @@ -36,11 +40,13 @@ public class CertificateViewModel extends ViewModel { CertificateViewModel(SchedulersFacade schedulersFacade, StoreTrustAnchorUseCase storeTrustAnchorUseCase, SaveIntermediateCertificateUseCase saveIntermediateCertificateUseCase, - SaveEndEntityCertificateUseCase saveEndEntityCertificateUseCase) { + SaveEndEntityCertificateUseCase saveEndEntityCertificateUseCase, + PreferencesRepository settingRepository) { this.mSchedulersFacade = schedulersFacade; this.storeTrustAnchorUseCase = storeTrustAnchorUseCase; this.saveIntermediateCertificateUseCase = saveIntermediateCertificateUseCase; this.saveEndEntityCertificateUseCase = saveEndEntityCertificateUseCase; + this.settingRepository = settingRepository; } @Override @@ -60,6 +66,11 @@ public LiveData getSuccess() { return mSuccess; } + public boolean isClientMode() + { + return settingRepository.getMode().equals(OtgcMode.CLIENT); + } + public void saveTrustAnchor(InputStream is) { mDisposables.add(storeTrustAnchorUseCase.execute(is) .subscribeOn(mSchedulersFacade.io()) diff --git a/otgc/src/main/java/org/openconnectivity/otgc/viewmodel/DoxsViewModel.java b/otgc/src/main/java/org/openconnectivity/otgc/viewmodel/DoxsViewModel.java index e2ea5ea..b532a41 100644 --- a/otgc/src/main/java/org/openconnectivity/otgc/viewmodel/DoxsViewModel.java +++ b/otgc/src/main/java/org/openconnectivity/otgc/viewmodel/DoxsViewModel.java @@ -59,6 +59,7 @@ import org.openconnectivity.otgc.domain.model.WifiNetwork; import org.openconnectivity.otgc.domain.usecase.wifi.RegisterScanResultsReceiverUseCase; import org.openconnectivity.otgc.domain.usecase.wifi.ScanWiFiNetworksUseCase; +import org.openconnectivity.otgc.domain.usecase.cloud.RegisterDeviceCloudUseCase; import java.util.Arrays; import java.util.List; @@ -91,6 +92,9 @@ public class DoxsViewModel extends BaseViewModel { private final CloudDiscoverDevicesUseCase cloudDiscoverDevicesUseCase; private final CloudRetrieveDeviceInfoUseCase cloudRetrieveDeviceInfoUseCase; private final CloudRetrieveDeviceRoleUseCase cloudRetrieveDeviceRoleUseCase; + private final RegisterDeviceCloudUseCase registerDeviceCloudUseCase; + + private final SchedulersFacade mSchedulersFacade; @@ -104,6 +108,7 @@ public class DoxsViewModel extends BaseViewModel { private final MutableLiveData> offboardResponse = new MutableLiveData<>(); private final MutableLiveData>> scanResponse = new MutableLiveData<>(); private final MutableLiveData> connectWifiEasySetupResponse = new MutableLiveData<>(); + private final MutableLiveData> registerDeviceCloudResponse = new MutableLiveData<>(); // Onboard selected devices private final MutableLiveData> onboardWaiting = new MutableLiveData<>(); @@ -137,7 +142,8 @@ public class DoxsViewModel extends BaseViewModel { SchedulersFacade schedulersFacade, CloudDiscoverDevicesUseCase cloudDiscoverDevicesUseCase, CloudRetrieveDeviceInfoUseCase cloudRetrieveDeviceInfoUseCase, - CloudRetrieveDeviceRoleUseCase cloudRetrieveDeviceRoleUseCase) { + CloudRetrieveDeviceRoleUseCase cloudRetrieveDeviceRoleUseCase, + RegisterDeviceCloudUseCase registerDeviceCloudUseCase) { this.mCheckConnectionUseCase = checkConnectionUseCase; this.mGetModeUseCase = getModeUseCase; this.mScanDevicesUseCase = scanDevicesUseCase; @@ -159,6 +165,7 @@ public class DoxsViewModel extends BaseViewModel { this.cloudDiscoverDevicesUseCase = cloudDiscoverDevicesUseCase; this.cloudRetrieveDeviceInfoUseCase = cloudRetrieveDeviceInfoUseCase; this.cloudRetrieveDeviceRoleUseCase = cloudRetrieveDeviceRoleUseCase; + this.registerDeviceCloudUseCase = registerDeviceCloudUseCase; this.mSchedulersFacade = schedulersFacade; @@ -403,6 +410,33 @@ public void offboard(Device deviceToOffboard) { )); } + public void registerDeviceCloud(Device deviceToRegister, String accessToken) { + mDisposables.add(mGetModeUseCase.execute() + .subscribeOn(mSchedulersFacade.io()) + .observeOn(mSchedulersFacade.ui()) + .subscribe( + mode -> { + if (mode.equals(OtgcMode.OBT)) { + + registerDeviceCloudUseCase.execute(deviceToRegister, accessToken) + + + .subscribeOn(mSchedulersFacade.io()) + .observeOn(mSchedulersFacade.ui()) + .subscribe( + () -> { + //notificationCenter.publish(NotificationKey.SCAN_DEVICES); + }, + throwable -> registerDeviceCloudResponse.setValue(Response.error(throwable)) + ); + } else { + registerDeviceCloudResponse.setValue(Response.success(null)); + } + }, + throwable -> registerDeviceCloudResponse.setValue(Response.error(throwable)) + )); + } + public void setDeviceName(String deviceId, String deviceName) { mDisposables.add(mSetDeviceNameUseCase.execute(deviceId, deviceName) .andThen(mGetDeviceNameUseCase.execute(deviceId)) diff --git a/otgc/src/main/res/menu/menu_owned_devices.xml b/otgc/src/main/res/menu/menu_owned_devices.xml index 62af339..9daf0ba 100644 --- a/otgc/src/main/res/menu/menu_owned_devices.xml +++ b/otgc/src/main/res/menu/menu_owned_devices.xml @@ -39,6 +39,10 @@ android:id="@+id/button_roles" app:showAsAction="never" android:title="@string/devices_cardview_menu_item_roles" /> + Inserte nombre del dispositivo Confirmar Cancelar + Inserte token de acceso + Confirmar + Cancelar Tipo de certificado: Certificado raĆ­z Certificado intermedio diff --git a/otgc/src/main/res/values/strings.xml b/otgc/src/main/res/values/strings.xml index faa6a2f..172746e 100644 --- a/otgc/src/main/res/values/strings.xml +++ b/otgc/src/main/res/values/strings.xml @@ -114,6 +114,9 @@ Insert device name Confirm Cancel + Insert access token + Confirm + Cancel Not Valid Certificate OK Certificate type: @@ -157,6 +160,7 @@ Offboard Set device name Wi-Fi Easy Setup + Register in cloud Scanning devices… Connect to Wi-Fi network In this moment there is no active Wi-Fi connection. Do you want to connect to a Wi-Fi network? @@ -312,7 +316,7 @@ Onboarding Tool and Generic Client Version %1$s - © 2020 Open Connectivity Foundation. + © 2021 Open Connectivity Foundation. All rights reserved. Powered by: DEKRA Testing and Certification, S.A.U.