/* * * Copyright (c) 2023 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #ifdef CONFIG_USE_ESP32_ECDSA_PERIPHERAL #include #endif // CONFIG_USE_ESP32_ECDSA_PERIPHERAL #define TAG "dac_provider" #ifdef CONFIG_SEC_CERT_DAC_PROVIDER namespace chip { namespace DeviceLayer { using namespace chip::Credentials; using namespace chip::DeviceLayer::Internal; namespace { static constexpr uint32_t kDACPrivateKeySize = 32; static constexpr uint32_t kDACPublicKeySize = 65; static constexpr uint8_t kPrivKeyOffset = 7; static constexpr uint8_t kPubKeyOffset = 56; CHIP_ERROR LoadKeypairFromRaw(ByteSpan privateKey, ByteSpan publicKey, Crypto::P256Keypair & keypair) { Crypto::P256SerializedKeypair serializedKeypair; ReturnErrorOnFailure(serializedKeypair.SetLength(privateKey.size() + publicKey.size())); memcpy(serializedKeypair.Bytes(), publicKey.data(), publicKey.size()); memcpy(serializedKeypair.Bytes() + publicKey.size(), privateKey.data(), privateKey.size()); return keypair.Deserialize(serializedKeypair); } } // namespace CHIP_ERROR ESP32SecureCertDACProvider ::GetCertificationDeclaration(MutableByteSpan & outBuffer) { #ifdef CONFIG_ENABLE_SET_CERT_DECLARATION_API return CopySpanToMutableSpan(mCD, outBuffer); #else size_t certSize; ReturnErrorOnFailure( ESP32Config::ReadConfigValueBin(ESP32Config::kConfigKey_CertDeclaration, outBuffer.data(), outBuffer.size(), certSize)); outBuffer.reduce_size(certSize); return CHIP_NO_ERROR; #endif // CONFIG_ENABLE_SET_CERT_DECLARATION_API } CHIP_ERROR ESP32SecureCertDACProvider ::GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer) { // We do not provide any FirmwareInformation. out_firmware_info_buffer.reduce_size(0); return CHIP_NO_ERROR; } CHIP_ERROR ESP32SecureCertDACProvider ::GetDeviceAttestationCert(MutableByteSpan & outBuffer) { char * dac_cert = NULL; uint32_t dac_len = 0; esp_err_t err = esp_secure_cert_get_device_cert(&dac_cert, &dac_len); if (err == ESP_OK && dac_cert != NULL && dac_len != 0) { ESP_FAULT_ASSERT(err == ESP_OK && dac_cert != NULL && dac_len != 0); VerifyOrReturnError(dac_len <= kMaxDERCertLength, CHIP_ERROR_UNSUPPORTED_CERT_FORMAT, esp_secure_cert_free_device_cert(dac_cert)); VerifyOrReturnError(dac_len <= outBuffer.size(), CHIP_ERROR_BUFFER_TOO_SMALL, esp_secure_cert_free_device_cert(dac_cert)); memcpy(outBuffer.data(), dac_cert, outBuffer.size()); outBuffer.reduce_size(dac_len); esp_secure_cert_free_device_cert(dac_cert); return CHIP_NO_ERROR; } ESP_LOGE(TAG, "esp_secure_cert_get_device_cert failed err:%d", err); return CHIP_ERROR_INCORRECT_STATE; } CHIP_ERROR ESP32SecureCertDACProvider ::GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer) { char * pai_cert = NULL; uint32_t pai_len = 0; esp_err_t err = esp_secure_cert_get_ca_cert(&pai_cert, &pai_len); if (err == ESP_OK && pai_cert != NULL && pai_len != 0) { ESP_FAULT_ASSERT(err == ESP_OK && pai_cert != NULL && pai_len != 0); VerifyOrReturnError(pai_len <= kMaxDERCertLength, CHIP_ERROR_UNSUPPORTED_CERT_FORMAT, esp_secure_cert_free_ca_cert(pai_cert)); VerifyOrReturnError(pai_len <= outBuffer.size(), CHIP_ERROR_BUFFER_TOO_SMALL, esp_secure_cert_free_ca_cert(pai_cert)); memcpy(outBuffer.data(), pai_cert, outBuffer.size()); outBuffer.reduce_size(pai_len); esp_secure_cert_free_ca_cert(pai_cert); return CHIP_NO_ERROR; } ESP_LOGE(TAG, "esp_secure_cert_get_ca_cert failed err:%d", err); return CHIP_ERROR_INCORRECT_STATE; } CHIP_ERROR ESP32SecureCertDACProvider ::SignWithDeviceAttestationKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer) { esp_err_t esp_err; esp_secure_cert_key_type_t keyType; CHIP_ERROR chipError; Crypto::P256ECDSASignature signature; VerifyOrReturnError(!outSignBuffer.empty(), CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(!messageToSign.empty(), CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(outSignBuffer.size() >= signature.Capacity(), CHIP_ERROR_BUFFER_TOO_SMALL); esp_err = esp_secure_cert_get_priv_key_type(&keyType); VerifyOrReturnError(esp_err == ESP_OK, CHIP_ERROR_INCORRECT_STATE, ESP_LOGE(TAG, "Failed to get the type of private key from secure cert partition, esp_err:%d", esp_err)); VerifyOrReturnError(keyType != ESP_SECURE_CERT_INVALID_KEY, CHIP_ERROR_INCORRECT_STATE, ESP_LOGE(TAG, "Private key type in secure cert partition is invalid")); // This flow is for devices supporting ECDSA peripheral if (keyType == ESP_SECURE_CERT_ECDSA_PERIPHERAL_KEY) { #ifdef CONFIG_USE_ESP32_ECDSA_PERIPHERAL Crypto::ESP32P256Keypair keypair; uint8_t efuseBlockId; esp_err = esp_secure_cert_get_priv_key_efuse_id(&efuseBlockId); VerifyOrReturnError(esp_err == ESP_OK, CHIP_ERROR_INVALID_KEY_ID, ESP_LOGE(TAG, "Failed to get the private key efuse block id, esp_err:%d", esp_err)); ESP_LOGD(TAG, "efuse block id:%u", efuseBlockId); chipError = keypair.Initialize(chip::Crypto::ECPKeyTarget::ECDSA, efuseBlockId); VerifyOrReturnError(chipError == CHIP_NO_ERROR, chipError, ESP_LOGE(TAG, "Failed to initialize the keypair err:%" CHIP_ERROR_FORMAT, chipError.Format())); chipError = keypair.ECDSA_sign_msg(messageToSign.data(), messageToSign.size(), signature); VerifyOrReturnError( chipError == CHIP_NO_ERROR, chipError, ESP_LOGE(TAG, "Failed to sign with device attestation key, err:%" CHIP_ERROR_FORMAT, chipError.Format())); #else return CHIP_ERROR_INCORRECT_STATE; #endif // CONFIG_USE_ESP32_ECDSA_PERIPHERAL } else // This flow is for devices which do not support ECDSA peripheral { #ifndef CONFIG_USE_ESP32_ECDSA_PERIPHERAL Crypto::P256Keypair keypair; char * sc_keypair = NULL; uint32_t sc_keypair_len = 0; esp_err = esp_secure_cert_get_priv_key(&sc_keypair, &sc_keypair_len); VerifyOrReturnError(esp_err == ESP_OK && sc_keypair != NULL && sc_keypair_len != 0, CHIP_ERROR_INCORRECT_STATE, ESP_LOGE(TAG, "esp_secure_cert_get_priv_key failed esp_err:%d", esp_err)); ESP_FAULT_ASSERT(esp_err == ESP_OK && sc_keypair != NULL && sc_keypair_len != 0); chipError = LoadKeypairFromRaw(ByteSpan(reinterpret_cast(sc_keypair + kPrivKeyOffset), kDACPrivateKeySize), ByteSpan(reinterpret_cast(sc_keypair + kPubKeyOffset), kDACPublicKeySize), keypair); VerifyOrReturnError(chipError == CHIP_NO_ERROR, chipError, esp_secure_cert_free_priv_key(sc_keypair)); chipError = keypair.ECDSA_sign_msg(messageToSign.data(), messageToSign.size(), signature); VerifyOrReturnError(chipError == CHIP_NO_ERROR, chipError, esp_secure_cert_free_priv_key(sc_keypair)); esp_secure_cert_free_priv_key(sc_keypair); #else return CHIP_ERROR_INCORRECT_STATE; #endif // !CONFIG_USE_ESP32_ECDSA_PERIPHERAL } return CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, outSignBuffer); } } // namespace DeviceLayer } // namespace chip #endif // CONFIG_SEC_CERT_DAC_PROVIDER