JNIDACProvider.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. *
  3. * Copyright (c) 2023 Project CHIP Authors
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. #include "JNIDACProvider.h"
  18. #include "lib/support/logging/CHIPLogging.h"
  19. #include <credentials/CHIPCert.h>
  20. #include <crypto/CHIPCryptoPAL.h>
  21. #include <cstdlib>
  22. #include <jni.h>
  23. #include <lib/core/CHIPError.h>
  24. #include <lib/support/CHIPJNIError.h>
  25. #include <lib/support/JniReferences.h>
  26. #include <lib/support/JniTypeWrappers.h>
  27. #include <lib/support/Span.h>
  28. using namespace chip;
  29. JNIDACProvider::JNIDACProvider(jobject provider)
  30. {
  31. JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
  32. VerifyOrReturn(env != nullptr, ChipLogError(Zcl, "Failed to GetEnvForCurrentThread for JNIDACProvider"));
  33. mJNIDACProviderObject = env->NewGlobalRef(provider);
  34. VerifyOrReturn(mJNIDACProviderObject != nullptr, ChipLogError(Zcl, "Failed to NewGlobalRef JNIDACProvider"));
  35. jclass JNIDACProviderClass = env->GetObjectClass(provider);
  36. VerifyOrReturn(JNIDACProviderClass != nullptr, ChipLogError(Zcl, "Failed to get JNIDACProvider Java class"));
  37. mGetCertificationDeclarationMethod = env->GetMethodID(JNIDACProviderClass, "GetCertificationDeclaration", "()[B");
  38. if (mGetCertificationDeclarationMethod == nullptr)
  39. {
  40. ChipLogError(Zcl, "Failed to access JNIDACProvider 'GetCertificationDeclaration' method");
  41. env->ExceptionClear();
  42. }
  43. mGetFirmwareInformationMethod = env->GetMethodID(JNIDACProviderClass, "GetFirmwareInformation", "()[B");
  44. if (mGetFirmwareInformationMethod == nullptr)
  45. {
  46. ChipLogError(Zcl, "Failed to access JNIDACProvider 'GetFirmwareInformation' method");
  47. env->ExceptionClear();
  48. }
  49. mGetDeviceAttestationCertMethod = env->GetMethodID(JNIDACProviderClass, "GetDeviceAttestationCert", "()[B");
  50. if (mGetDeviceAttestationCertMethod == nullptr)
  51. {
  52. ChipLogError(Zcl, "Failed to access JNIDACProvider 'GetDeviceAttestationCert' method");
  53. env->ExceptionClear();
  54. }
  55. mGetProductAttestationIntermediateCertMethod =
  56. env->GetMethodID(JNIDACProviderClass, "GetProductAttestationIntermediateCert", "()[B");
  57. if (mGetProductAttestationIntermediateCertMethod == nullptr)
  58. {
  59. ChipLogError(Zcl, "Failed to access JNIDACProvider 'GetProductAttestationIntermediateCert' method");
  60. env->ExceptionClear();
  61. }
  62. mGetDeviceAttestationCertPrivateKeyMethod = env->GetMethodID(JNIDACProviderClass, "GetDeviceAttestationCertPrivateKey", "()[B");
  63. if (mGetDeviceAttestationCertPrivateKeyMethod == nullptr)
  64. {
  65. ChipLogError(Zcl, "Failed to access JNIDACProvider 'GetDeviceAttestationCertPrivateKey' method");
  66. env->ExceptionClear();
  67. }
  68. mGetDeviceAttestationCertPublicKeyKeyMethod =
  69. env->GetMethodID(JNIDACProviderClass, "GetDeviceAttestationCertPublicKeyKey", "()[B");
  70. if (mGetDeviceAttestationCertPublicKeyKeyMethod == nullptr)
  71. {
  72. ChipLogError(Zcl, "Failed to access JNIDACProvider 'GetDeviceAttestationCertPublicKeyKey' method");
  73. env->ExceptionClear();
  74. }
  75. }
  76. CHIP_ERROR JNIDACProvider::GetJavaByteByMethod(jmethodID method, MutableByteSpan & out_buffer)
  77. {
  78. JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
  79. VerifyOrReturnLogError(mJNIDACProviderObject != nullptr, CHIP_ERROR_INCORRECT_STATE);
  80. VerifyOrReturnLogError(method != nullptr, CHIP_ERROR_INCORRECT_STATE);
  81. VerifyOrReturnLogError(env != nullptr, CHIP_JNI_ERROR_NO_ENV);
  82. jbyteArray outArray = (jbyteArray) env->CallObjectMethod(mJNIDACProviderObject, method);
  83. if (env->ExceptionCheck())
  84. {
  85. ChipLogError(Zcl, "Java exception in get Method");
  86. env->ExceptionDescribe();
  87. env->ExceptionClear();
  88. return CHIP_ERROR_INCORRECT_STATE;
  89. }
  90. if (outArray == nullptr || env->GetArrayLength(outArray) <= 0)
  91. {
  92. out_buffer.reduce_size(0);
  93. return CHIP_NO_ERROR;
  94. }
  95. JniByteArray JniOutArray(env, outArray);
  96. return CopySpanToMutableSpan(JniOutArray.byteSpan(), out_buffer);
  97. }
  98. CHIP_ERROR JNIDACProvider::GetCertificationDeclaration(MutableByteSpan & out_cd_buffer)
  99. {
  100. ChipLogProgress(Zcl, "Received GetCertificationDeclaration");
  101. return GetJavaByteByMethod(mGetCertificationDeclarationMethod, out_cd_buffer);
  102. }
  103. CHIP_ERROR JNIDACProvider::GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer)
  104. {
  105. ChipLogProgress(Zcl, "Received GetFirmwareInformation");
  106. return GetJavaByteByMethod(mGetFirmwareInformationMethod, out_firmware_info_buffer);
  107. }
  108. CHIP_ERROR JNIDACProvider::GetDeviceAttestationCert(MutableByteSpan & out_dac_buffer)
  109. {
  110. ChipLogProgress(Zcl, "Received GetDeviceAttestationCert");
  111. return GetJavaByteByMethod(mGetDeviceAttestationCertMethod, out_dac_buffer);
  112. }
  113. CHIP_ERROR JNIDACProvider::GetProductAttestationIntermediateCert(MutableByteSpan & out_pai_buffer)
  114. {
  115. ChipLogProgress(Zcl, "Received GetProductAttestationIntermediateCert");
  116. return GetJavaByteByMethod(mGetProductAttestationIntermediateCertMethod, out_pai_buffer);
  117. }
  118. // TODO: This should be moved to a method of P256Keypair
  119. CHIP_ERROR LoadKeypairFromRaw(ByteSpan private_key, ByteSpan public_key, Crypto::P256Keypair & keypair)
  120. {
  121. Crypto::P256SerializedKeypair serialized_keypair;
  122. ReturnErrorOnFailure(serialized_keypair.SetLength(private_key.size() + public_key.size()));
  123. memcpy(serialized_keypair.Bytes(), public_key.data(), public_key.size());
  124. memcpy(serialized_keypair.Bytes() + public_key.size(), private_key.data(), private_key.size());
  125. return keypair.Deserialize(serialized_keypair);
  126. }
  127. CHIP_ERROR JNIDACProvider::SignWithDeviceAttestationKey(const ByteSpan & digest_to_sign, MutableByteSpan & out_signature_buffer)
  128. {
  129. ChipLogProgress(Zcl, "Received SignWithDeviceAttestationKey");
  130. Crypto::P256ECDSASignature signature;
  131. Crypto::P256Keypair keypair;
  132. VerifyOrReturnError(!out_signature_buffer.empty(), CHIP_ERROR_INVALID_ARGUMENT);
  133. VerifyOrReturnError(!digest_to_sign.empty(), CHIP_ERROR_INVALID_ARGUMENT);
  134. VerifyOrReturnError(out_signature_buffer.size() >= signature.Capacity(), CHIP_ERROR_BUFFER_TOO_SMALL);
  135. uint8_t privateKeyBuf[Crypto::kP256_PrivateKey_Length];
  136. MutableByteSpan privateKeyBufSpan(privateKeyBuf);
  137. ReturnErrorOnFailure(GetJavaByteByMethod(mGetDeviceAttestationCertPrivateKeyMethod, privateKeyBufSpan));
  138. uint8_t publicKeyBuf[Crypto::kP256_PublicKey_Length];
  139. MutableByteSpan publicKeyBufSpan(publicKeyBuf);
  140. ReturnErrorOnFailure(GetJavaByteByMethod(mGetDeviceAttestationCertPublicKeyKeyMethod, publicKeyBufSpan));
  141. // In a non-exemplary implementation, the public key is not needed here. It is used here merely because
  142. // Crypto::P256Keypair is only (currently) constructable from raw keys if both private/public keys are present.
  143. ReturnErrorOnFailure(LoadKeypairFromRaw(privateKeyBufSpan, publicKeyBufSpan, keypair));
  144. ReturnErrorOnFailure(keypair.ECDSA_sign_msg(digest_to_sign.data(), digest_to_sign.size(), signature));
  145. return CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, out_signature_buffer);
  146. }