2 * Copyright (c) 2017 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 #import <Foundation/Foundation.h>
26 #import "OTBottledPeer.h"
27 #import "OTBottledPeerSigned.h"
28 #import "SFPublicKey+SPKI.h"
29 #import "OTIdentity.h"
31 #import <SecurityFoundation/SFEncryptionOperation.h>
32 #import <SecurityFoundation/SFSigningOperation.h>
33 #import <SecurityFoundation/SFDigestOperation.h>
34 #import <SecurityFoundation/SFKey.h>
35 #import <SecurityFoundation/SFKey_Private.h>
37 #import <corecrypto/cchkdf.h>
38 #import <corecrypto/ccsha2.h>
39 #import <corecrypto/ccec.h>
41 #include <utilities/debugging.h>
43 @interface OTBottledPeerSigned ()
44 @property (nonatomic, strong) OTBottledPeer* bp;
45 @property (nonatomic, strong) NSData* signatureUsingEscrowKey;
46 @property (nonatomic, strong) NSData* signatureUsingPeerKey;
47 @property (nonatomic, strong) NSData* escrowSigningPublicKey;
50 @implementation OTBottledPeerSigned
53 - (nullable instancetype) initWithBottledPeer:(OTBottledPeer*)bp
54 escrowedSigningKey:(SFECKeyPair *)escrowedSigningKey
55 peerSigningKey:(SFECKeyPair *)peerSigningKey
56 error:(NSError**)error
61 _escrowSigningSPKI = [escrowedSigningKey.publicKey asSPKI];
62 SFEC_X962SigningOperation* xso = [OTBottledPeerSigned signingOperation];
63 _signatureUsingEscrowKey = [xso sign:bp.data withKey:escrowedSigningKey error:error].signature;
64 if (!_signatureUsingEscrowKey) {
67 _signatureUsingPeerKey = [xso sign:bp.data withKey:peerSigningKey error:error].signature;
68 if (!_signatureUsingPeerKey) {
75 -(NSString*) escrowSigningPublicKeyHash
77 const struct ccdigest_info *di = ccsha384_di();
78 NSMutableData* result = [[NSMutableData alloc] initWithLength:ccsha384_di()->output_size];
80 ccdigest(di, [self.escrowSigningPublicKey length], [self.escrowSigningPublicKey bytes], [result mutableBytes]);
82 return [result base64EncodedStringWithOptions:0];
85 // Verify signatures, or return nil
86 - (nullable instancetype) initWithBottledPeer:(OTBottledPeer*)bp
87 signatureUsingEscrow:(NSData*)signatureUsingEscrow
88 signatureUsingPeerKey:(NSData*)signatureUsingPeerKey
89 escrowedSigningPubKey:(SFECPublicKey *)escrowedSigningPubKey
90 error:(NSError**)error
95 _escrowSigningSPKI = [escrowedSigningPubKey asSPKI];
96 _signatureUsingPeerKey = signatureUsingPeerKey;
97 _signatureUsingEscrowKey = signatureUsingEscrow;
98 _escrowSigningPublicKey = [escrowedSigningPubKey keyData];
100 SFEC_X962SigningOperation* xso = [OTBottledPeerSigned signingOperation];
102 SFSignedData *escrowSigned = [[SFSignedData alloc] initWithData:bp.data signature:signatureUsingEscrow];
103 if (![xso verify:escrowSigned withKey:escrowedSigningPubKey error:error]) {
106 SFSignedData *peerSigned = [[SFSignedData alloc] initWithData:bp.data signature:signatureUsingPeerKey];
107 if (![xso verify:peerSigned withKey:bp.peerSigningKey.publicKey error:error]) {
110 //stuff restored keys in the keychain
111 [OTIdentity storeOctagonIdentityIntoKeychain:self.bp.peerSigningKey restoredEncryptionKey:self.bp.peerEncryptionKey escrowSigningPubKeyHash:self.escrowSigningPublicKeyHash restoredPeerID:self.bp.spID error:error];
116 + (SFEC_X962SigningOperation*) signingOperation
118 SFECKeySpecifier *keySpecifier = [[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384];
119 id<SFDigestOperation> digestOperation = [[SFSHA384DigestOperation alloc] init];
120 return [[SFEC_X962SigningOperation alloc] initWithKeySpecifier:keySpecifier digestOperation:digestOperation];
123 + (BOOL) verifyBottleSignature:(NSData*)data signature:(NSData*)signature key:(_SFECPublicKey*) pubKey error:(NSError**)error
125 SFEC_X962SigningOperation* xso = [OTBottledPeerSigned signingOperation];
127 SFSignedData *peerSigned = [[SFSignedData alloc] initWithData:data signature:signature];
129 return ([xso verify:peerSigned withKey:pubKey error:error] != nil);
133 - (nullable instancetype) initWithBottledPeerRecord:(OTBottledPeerRecord *)record
134 escrowKeys:(OTEscrowKeys *)escrowKeys
135 error:(NSError**)error
137 OTBottledPeer *bp = [[OTBottledPeer alloc] initWithData:record.bottle
138 escrowKeys:escrowKeys
143 return [self initWithBottledPeer:bp
144 signatureUsingEscrow:record.signatureUsingEscrowKey
145 signatureUsingPeerKey:record.signatureUsingPeerKey
146 escrowedSigningPubKey:escrowKeys.signingKey.publicKey
150 - (OTBottledPeerRecord *)asRecord:(NSString*)escrowRecordID
152 OTBottledPeerRecord *rec = [[OTBottledPeerRecord alloc] init];
153 rec.spID = self.bp.spID;
154 rec.escrowRecordID = [escrowRecordID copy];
155 rec.peerSigningSPKI = [self.bp.peerSigningKey.publicKey asSPKI];
156 rec.escrowedSigningSPKI = self.escrowSigningSPKI;
157 rec.bottle = self.bp.data;
158 rec.signatureUsingPeerKey = self.signatureUsingPeerKey;
159 rec.signatureUsingEscrowKey = self.signatureUsingEscrowKey;
160 rec.launched = @"NO";