SysIntegrity API

Service Features

  1. TEE-based system integrity check results: The API evaluates the system integrity in the secure boot process in the Trusted Execution Environment (TEE) and will dynamically evaluate the system integrity. The check results are highly reliable.
  2. Trustworthy system integrity check results: System integrity check results request the certificate signature. The server uses the X.509 digital certificate to sign the system integrity check results and transfers the signed JWS-format results to the SysIntegrity API. The signed results cannot be tampered with.

Service Process

  1. Your app integrates the Safety Detect SDK and calls the SysIntegrity API.
  2. Safety Detect requests the TSMS server to sign the check result.
  3. Your app requests the check result.

Use Cases

An app calls the SysIntegrity API to check the system integrity of a device. If the device is insecure, the app will take appropriate measures.

App Development

To call the SysIntegrity API, perform the following steps:

  1. Obtain a nonce value.
    When calling the SysIntegrity API of Safety Detect, you must pass a nonce value that is randomly generated and will be contained in the check result. You can check the nonce value to verify that the returned result corresponds to your request and does not encounter replay attacks. A nonce value must contain 16 to 66 bytes. Otherwise, the API call may fail.
    注意

    A nonce value must meet the following requirements:

    • Contain 16 to 66 bytes.
    • (Recommended) Be randomly generated by the server for each request.
  2. Request the SysIntegrity API of Safety Detect.

    Safety Detect provides two SysIntegrity APIs which require different parameters. However, both the nonce and APP ID parameters are required for the two APIs. As for the sysIntegrity(SysIntegrityRequest sysIntegrityRequest) API, you also need to pass the signature verification mode to SysIntegrityRequest. The signature verification mode is the same as that specified by alg in the header of the obtained JWS-format response.

    • nonce: obtained nonce value.
    • APP ID: ID of an app.

    You can perform the following operations to obtain the app ID:

    1. Sign in to AppGallery Connect and click My projects.
    2. Find your app project, and click the desired app name.
    3. Go to Project settings > General information, and view the app ID in the App information area.
    Java
    Kotlin
    private void invokeSysIntegrity() {
       SafetyDetectClient mClient = SafetyDetect.getClient(getActivity());
       // TODO(developer): Change the value of nonce to a random value generated by the server.
       byte[] nonce = Random value generated by the server
       String alg = "PS256"
       SysIntegrityRequest  sysintegrityrequest = new SysIntegrityRequest();
       sysintegrityrequest.setAppId("3*******");
       sysintegrityrequest.setNonce(nonce);
       sysintegrityrequest.setAlg(alg);                                                              
       Task task = mClient.sysIntegrity(sysintegrityrequest);
       task.addOnSuccessListener(new OnSuccessListener<SysIntegrityResp>() {
           @Override
           public void onSuccess(SysIntegrityResp response) {
               // Indicates that communication with the service was successful.
               // Use response.getResult() to obtain the result data.
               String jwsStr = response.getResult();
           }
       }).addOnFailureListener(new OnFailureListener() {
           @Override
           public void onFailure(Exception e) {
               // An error occurred during communication with the service.
               if (e instanceof ApiException) {
                   // An error with the HMS API contains some
                   // additional details.
                   ApiException apiException = (ApiException) e;
                   // You can retrieve the status code using
                   // the apiException.getStatusCode() method.
                   Log.e(TAG, "Error: " + SafetyDetectStatusCodes.getStatusCodeString(apiException.getStatusCode()) + ": " + apiException.getMessage());
               } else {
                   // A different, unknown type of error occurred.
                   Log.e(TAG, "ERROR:" + e.getMessage());
               }
           }
       });
    }
      private fun invokeSysIntegrity() {
    // TODO(developer): Change the value of nonce to a random value generated by the server.
             val nonce = Random value generated by the server
    // TODO (developer): Change your app ID. You can obtain your app ID in AppGallery Connect.
             val alg = "PS256"
             val sysIntegrityRequest = SysIntegrityRequest()
             sysIntegrityRequest.appId = APP_ID
             sysIntegrityRequest.nonce = nonce
             sysIntegrityRequest.alg = alg
    
             SafetyDetect.getClient(activity)
                     .sysIntegrity(sysIntegrityRequest)
                     .addOnSuccessListener { response -> // Indicates communication with the service was successful.
     // Use response.getResult() to obtain the result data.
                         val jwsStr = response.result
    
    // Process the result data here.
                         val jwsSplit = jwsStr.split(".").toTypedArray()
                         val jwsPayloadStr = jwsSplit[1]
                         val payloadDetail = String(Base64.decode(jwsPayloadStr.toByteArray(StandardCharsets.UTF_8), Base64.URL_SAFE), StandardCharsets.UTF_8)
                         try {
                             val jsonObject = JSONObject(payloadDetail)
                             val basicIntegrity = jsonObject.getBoolean("basicIntegrity")
                             fg_button_sys_integrity_go.setBackgroundResource(if (basicIntegrity) R.drawable.btn_round_green else R.drawable.btn_round_red)
                             fg_button_sys_integrity_go.setText(R.string.rerun)
                             val isBasicIntegrity = basicIntegrity.toString()
                             val basicIntegrityResult = "Basic Integrity: $isBasicIntegrity"
                             fg_payloadBasicIntegrity.text = basicIntegrityResult
                             if (!basicIntegrity) {
                                 val advice = "Advice: " + jsonObject.getString("advice")
                                 fg_payloadAdvice.text = advice
                             }
                         } catch (e: JSONException) {
                             val errorMsg = e.message
                             Log.e(TAG, errorMsg ?: "unknown error")
                         }
    
    
                     }
                     .addOnFailureListener { e -> // There was an error communicating with the service.
                         val errorMsg: String?
                         errorMsg = if (e is ApiException) {
    // An error with the HMS API contains some additional details.
                             val apiException = e as ApiException
                             SafetyDetectStatusCodes.getStatusCodeString(apiException.statusCode) +
                                     ": " + apiException.message
    // You can use the apiException.getStatusCode() method to obtain the status code.
                         } else {
    // An unknown type of error has occurred.
                             e.message
                         }
                         Log.e(TAG, errorMsg)
                         Toast.makeText(activity?.applicationContext, errorMsg, Toast.LENGTH_SHORT).show()
                         fg_button_sys_integrity_go.setBackgroundResource(R.drawable.btn_round_yellow)
                         fg_button_sys_integrity_go.setText(R.string.rerun)
                    }
         }
  3. Verify the check result on your server.

    HMS Core (APK) sends the check result to the Huawei server to verify the certificate, and returns the result to you through the SysIntegrityResp object. You can use the getResult method of the object to obtain the response in JSON Web Signature (JWS) format.

    1. Parse the JWS-format result to obtain header, payload, and signature.
    2. Obtain the certificate chain from header and use the Huawei CBG Root CA certificate to verify it.
    3. Verify the domain name of the leaf certificate in the certificate chain. The correct domain name is sysintegrity.platform.hicloud.com.
    4. Obtain the signature from signature and verify it.
    5. Obtain the integrity verification result from payload. The format and example are as follows:
      {
               "advice": "RESTORE_TO_FACTORY_ROM",
               "apkCertificateDigestSha256": ["gwpz0q/WtjtJZZK5lTXl74fI/8QAKGLAhdhlznKkLhQ="],
               "apkDigestSha256": "nBrInk2DLVQrgcQ1DXYnIUIMnjJ+mVo0lwUicF7OzJM=",
               "apkPackageName": "com.huawei.hms.safetydetectsample",
               "appId": "1*******",
               "basicIntegrity": false,
               "detail": ["root", "unlocked"],
               "nonce": "UjJScmEyNGZWbTV4YTJNZw==",
               "timestampMs": 1612683290520
      }

      If the value of the basicIntegrity field in the check result is false, the detail field will list the specific reason why the value false is returned. For details, please refer to getResult. You can decide whether to remind users of the risks based on your security requirements.

说明

For details about the fields, please refer to API Reference.

For details about the verification logic, please refer to SysIntegrity in Client Sample Code.

Precautions

  1. The current solution has combined the server and client to mitigate security risks. However, the SysIntegrity API cannot mitigate all security risks.
  2. When calling the SysIntegrity API, you should consider relevant risks caused by possibly incorrect check results and impacts to users. The check result of the SysIntegrity API can be used as one of the system security proofs. However, you are advised not to use the check result as the only proof to determine whether the current device is secure. You are advised to take extra measures to further reduce risks.
搜索
请输入您想要搜索的关键词