Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Darwin CHIPKeypair usable in a few more cases. #18458

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

@interface CHIPToolKeypair : NSObject <CHIPKeypair>
- (BOOL)initialize;
- (NSData *)ECDSA_sign_hash:(NSData *)hash;
- (NSData *)ECDSA_sign_message_raw:(NSData *)message;
- (SecKeyRef)pubkey;
- (CHIP_ERROR)Serialize:(chip::Crypto::P256SerializedKeypair &)output;
- (CHIP_ERROR)Deserialize:(chip::Crypto::P256SerializedKeypair &)input;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ - (BOOL)initialize
return _mKeyPair.Initialize() == CHIP_NO_ERROR;
}

- (NSData *)ECDSA_sign_hash:(NSData *)hash
- (NSData *)ECDSA_sign_message_raw:(NSData *)message
{
chip::Crypto::P256ECDSASignature signature;
NSData * out_signature;
CHIP_ERROR signing_error = _mKeyPair.ECDSA_sign_hash((const uint8_t *) [hash bytes], (const size_t)[hash length], signature);
CHIP_ERROR signing_error = _mKeyPair.ECDSA_sign_msg((const uint8_t *) [message bytes], (size_t)[message length], signature);
if (signing_error != CHIP_NO_ERROR)
return nil;
out_signature = [NSData dataWithBytes:signature.Bytes() length:signature.Length()];
Expand Down
4 changes: 2 additions & 2 deletions src/crypto/CHIPCryptoPAL.h
Original file line number Diff line number Diff line change
Expand Up @@ -537,8 +537,8 @@ CHIP_ERROR EcdsaRawSignatureToAsn1(size_t fe_length_bytes, const ByteSpan & raw_
* @param[in] fe_length_bytes Field Element length in bytes (e.g. 32 for P256 curve)
* @param[in] asn1_sig ASN.1 DER signature input
* @param[out] out_raw_sig Raw signature of <r,s> concatenated format output buffer. Size must be at
* least >= `2 * fe_length_bytes`. On CHIP_NO_ERROR, the out_asn1_sig buffer will be re-assigned
* to have the correct size based on variable-length output.
* least >= `2 * fe_length_bytes`. On CHIP_NO_ERROR, the out_raw_sig buffer will be re-assigned
* to have the correct size (2 * fe_length_bytes).
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
*/
CHIP_ERROR EcdsaAsn1SignatureToRaw(size_t fe_length_bytes, const ByteSpan & asn1_sig, MutableByteSpan & out_raw_sig);
Expand Down
4 changes: 2 additions & 2 deletions src/darwin/CHIPTool/CHIPTool/Framework Helpers/FabricKeys.m
Original file line number Diff line number Diff line change
Expand Up @@ -207,11 +207,11 @@ - (instancetype)init
return self;
}

- (NSData *)ECDSA_sign_hash:(NSData *)hash
- (NSData *)ECDSA_sign_message_DER:(NSData *)message
{
CFErrorRef error = NULL;
CFDataRef outData
= SecKeyCreateSignature(_privateKey, kSecKeyAlgorithmECDSASignatureRFC4754, (__bridge CFDataRef) hash, &error);
= SecKeyCreateSignature(_privateKey, kSecKeyAlgorithmECDSASignatureMessageX962SHA256, (__bridge CFDataRef) message, &error);

if (error != noErr) {
NSLog(@"Failed to sign cert: %@", (__bridge NSError *) error);
Expand Down
35 changes: 27 additions & 8 deletions src/darwin/Framework/CHIP/CHIPKeypair.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,37 @@ NS_ASSUME_NONNULL_BEGIN

@protocol CHIPKeypair <NSObject>
@required
/**
* @brief Return public key for the keypair.
*/
- (SecKeyRef)pubkey;

@optional
/**
* @brief A function to sign a hash using ECDSA
* @param hash Hash that needs to be signed
* @brief A function to sign a message using ECDSA
*
* @return Returns A signature that consists of: 2 EC elements (r and s), in raw <r,s> point form (see SEC1).
**/
- (NSData *)ECDSA_sign_hash:(NSData *)hash;
* @param message Message that needs to be signed
*
* @return A signature that consists of: 2 EC elements (r and s), in raw <r,s>
* point form (see SEC1). Sometimes also called RFC 4754 form or P1363
* form.
*
* Either this selector or ECDSA_sign_message_DER must be supported by a
* CHIPKeypair.
*/
- (NSData *)ECDSA_sign_message_raw:(NSData *)message;

/** @brief Return public key for the keypair.
**/
- (SecKeyRef)pubkey;
/**
* @brief A function to sign a message using ECDSA
*
* @param message Message that needs to be signed
*
* @return An ASN.1 DER-encoded signature (per X9.62).
*
* Either this selector or ECDSA_sign_message_raw must be supported by a
* CHIPKeypair.
*/
- (NSData *)ECDSA_sign_message_DER:(NSData *)message;

@end

Expand Down
64 changes: 40 additions & 24 deletions src/darwin/Framework/CHIP/CHIPP256KeypairBridge.mm
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
*/

#import "CHIPP256KeypairBridge.h"
#import "NSDataSpanConversion.h"

#import <CommonCrypto/CommonDigest.h>
#import <Security/SecKey.h>
#include <string>

Expand All @@ -28,6 +28,12 @@

CHIP_ERROR CHIPP256KeypairBridge::Init(id<CHIPKeypair> keypair)
{
if (![keypair respondsToSelector:@selector(ECDSA_sign_message_DER:)]
&& ![keypair respondsToSelector:@selector(ECDSA_sign_message_raw:)]) {
// Not a valid CHIPKeypair implementation.
return CHIP_ERROR_INVALID_ARGUMENT;
}

mKeypair = keypair;
return setPubkey();
}
Expand Down Expand Up @@ -76,20 +82,42 @@
return CHIP_ERROR_INCORRECT_STATE;
}
NSData * msgData = [NSData dataWithBytes:msg length:msg_length];
NSMutableData * hashedData = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];
CC_SHA256(msgData.bytes, (CC_LONG) msgData.length, (unsigned char *) hashedData.mutableBytes);
CHIP_LOG_DEBUG("Generated Msg hash, signing hash now");
NSData * signature = [mKeypair ECDSA_sign_hash:hashedData];
if (!signature) {
CHIP_LOG_ERROR("ECDSA sign msg failure: no signature returned");
return CHIP_ERROR_INTERNAL;
NSData * signature;
if ([mKeypair respondsToSelector:@selector(ECDSA_sign_message_DER:)]) {
signature = [mKeypair ECDSA_sign_message_DER:msgData];
if (!signature) {
CHIP_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) {
CHIP_LOG_ERROR("Converting ASN.1 DER signature to raw form failed: %s", chip::ErrorStr(err));
return err;
}

signature = AsData(rawSignature);
if (!signature) {
CHIP_LOG_ERROR("Failed to create NSData for raw signature");
return CHIP_ERROR_INTERNAL;
}
} else {
signature = [mKeypair ECDSA_sign_message_raw:msgData];
if (!signature) {
CHIP_LOG_ERROR("ECDSA sign msg failure: no signature returned");
return CHIP_ERROR_INTERNAL;
}
}
if (signature.length > out_signature.Capacity()) {
CHIP_LOG_ERROR("ECDSA sign msg failure: unexpected signature size %tu vs %tu ", signature.length, out_signature.Capacity());
CHIP_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, signature.bytes, signature.length);
std::memcpy(out_signature.Bytes(), signature.bytes, signature.length);
return CHIP_NO_ERROR;
}

Expand All @@ -98,20 +126,8 @@
if (!HasKeypair()) {
return CHIP_ERROR_INCORRECT_STATE;
}
NSData * hashData = [NSData dataWithBytes:hash length:hash_length];
NSData * signature = [mKeypair ECDSA_sign_hash:hashData];
if (!signature) {
CHIP_LOG_ERROR("ECDSA sign hash failure: no signature returned");
return CHIP_ERROR_INTERNAL;
}
if (signature.length > out_signature.Capacity()) {
CHIP_LOG_ERROR(
"ECDSA sign hash failure: unexpected signature size %tu vs %tu ", signature.length, out_signature.Capacity());
return CHIP_ERROR_NO_MEMORY;
}
out_signature.SetLength(signature.length);
std::memcpy(out_signature, signature.bytes, signature.length);
return CHIP_NO_ERROR;

return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
}

CHIP_ERROR CHIPP256KeypairBridge::ECDH_derive_secret(
Expand Down
4 changes: 2 additions & 2 deletions src/darwin/Framework/CHIPTests/CHIPTestKeys.m
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ - (instancetype)init
return self;
}

- (NSData *)ECDSA_sign_hash:(NSData *)hash
- (NSData *)ECDSA_sign_message_DER:(NSData *)message
{
CFErrorRef error = NULL;
CFDataRef outData
= SecKeyCreateSignature(_privateKey, kSecKeyAlgorithmECDSASignatureRFC4754, (__bridge CFDataRef) hash, &error);
= SecKeyCreateSignature(_privateKey, kSecKeyAlgorithmECDSASignatureMessageX962SHA256, (__bridge CFDataRef) message, &error);

if (error != noErr) {
NSLog(@"Failed to sign cert: %@", (__bridge NSError *) error);
Expand Down