blob: d253baa8dbf95c72ed0bf9522b80c92fd5769fa6 [file] [log] [blame]
/**
*
* Copyright (c) 2021 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.
*/
#import "MTRP256KeypairBridge.h"
#import "NSDataSpanConversion.h"
#import <Security/Security.h>
#include <string>
#import "MTRKeypair.h"
#import "MTRLogging_Internal.h"
using namespace chip::Crypto;
CHIP_ERROR MTRP256KeypairBridge::Init(id<MTRKeypair> keypair)
{
if (![keypair respondsToSelector:@selector(signMessageECDSA_DER:)]
&& ![keypair respondsToSelector:@selector(signMessageECDSA_RAW:)]) {
// Not a valid MTRKeypair implementation.
MTR_LOG_ERROR("Keypair does not support message signing");
return CHIP_ERROR_INVALID_ARGUMENT;
}
mKeypair = keypair;
return setPubkey();
}
CHIP_ERROR MTRP256KeypairBridge::Initialize(ECPKeyTarget key_target)
{
if (!HasKeypair()) {
return CHIP_ERROR_INCORRECT_STATE;
}
// Our keypair is always initialized.
return CHIP_NO_ERROR;
}
CHIP_ERROR MTRP256KeypairBridge::Serialize(P256SerializedKeypair & output) const
{
if (!HasKeypair()) {
return CHIP_ERROR_INCORRECT_STATE;
}
return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
}
CHIP_ERROR MTRP256KeypairBridge::Deserialize(P256SerializedKeypair & input)
{
if (!HasKeypair()) {
return CHIP_ERROR_INCORRECT_STATE;
}
return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
}
CHIP_ERROR MTRP256KeypairBridge::NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) const
{
if (!HasKeypair()) {
return CHIP_ERROR_INCORRECT_STATE;
}
return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
}
CHIP_ERROR MTRP256KeypairBridge::ECDSA_sign_msg(const uint8_t * msg, size_t msg_length, P256ECDSASignature & out_signature) const
{
if (!HasKeypair()) {
MTR_LOG_ERROR("ECDSA sign msg failure: no keypair to sign with.");
return CHIP_ERROR_INCORRECT_STATE;
}
NSData * msgData = [NSData dataWithBytes:msg length:msg_length];
NSData * signature;
if ([mKeypair respondsToSelector:@selector(signMessageECDSA_DER:)]) {
signature = [mKeypair signMessageECDSA_DER:msgData];
if (!signature) {
MTR_LOG_ERROR("ECDSA sign msg failure: no signature returned");
return CHIP_ERROR_INTERNAL;
}
uint8_t buf[kP256_ECDSA_Signature_Length_Raw];
chip::MutableByteSpan rawSignature(buf);
CHIP_ERROR err = EcdsaAsn1SignatureToRaw(kP256_FE_Length, AsByteSpan(signature), rawSignature);
if (err != CHIP_NO_ERROR) {
MTR_LOG_ERROR("Converting ASN.1 DER signature to raw form failed: %s", chip::ErrorStr(err));
return err;
}
signature = AsData(rawSignature);
if (!signature) {
MTR_LOG_ERROR("Failed to create NSData for raw signature");
return CHIP_ERROR_INTERNAL;
}
} else {
signature = [mKeypair signMessageECDSA_RAW:msgData];
if (!signature) {
MTR_LOG_ERROR("ECDSA sign msg failure: no signature returned");
return CHIP_ERROR_INTERNAL;
}
}
if (signature.length > out_signature.Capacity()) {
MTR_LOG_ERROR("ECDSA sign msg failure: unexpected signature size %llu vs %llu", static_cast<uint64_t>(signature.length),
static_cast<uint64_t>(out_signature.Capacity()));
return CHIP_ERROR_NO_MEMORY;
}
out_signature.SetLength(signature.length);
std::memcpy(out_signature.Bytes(), signature.bytes, signature.length);
return CHIP_NO_ERROR;
}
CHIP_ERROR MTRP256KeypairBridge::ECDH_derive_secret(
const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const
{
if (!HasKeypair()) {
return CHIP_ERROR_INCORRECT_STATE;
}
return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
}
CHIP_ERROR MTRP256KeypairBridge::setPubkey() { return MatterPubKeyFromSecKeyRef([mKeypair publicKey], &mPubkey); }
CHIP_ERROR MTRP256KeypairBridge::MatterPubKeyFromSecKeyRef(SecKeyRef pubkeyRef, P256PublicKey * matterPubKey)
{
if (!pubkeyRef) {
MTR_LOG_ERROR("Unable to initialize Pubkey");
return CHIP_ERROR_INTERNAL;
}
NSData * pubkeyData = (__bridge_transfer NSData *) SecKeyCopyExternalRepresentation(pubkeyRef, nil);
if (!pubkeyData) {
MTR_LOG_ERROR("Unable to copy external representation for publicKey ref, cannot initialize publicKey");
return CHIP_ERROR_INTERNAL;
}
if (pubkeyData.length != kP256_PublicKey_Length) {
MTR_LOG_ERROR("Unexpected publicKey length, cannot initialize publicKey");
return CHIP_ERROR_INTERNAL;
}
chip::FixedByteSpan<kP256_PublicKey_Length> pubkeyBytes((const uint8_t *) pubkeyData.bytes);
*matterPubKey = pubkeyBytes;
return CHIP_NO_ERROR;
}