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 "OTIdentity.h"
30 #import <SecurityFoundation/SFEncryptionOperation.h>
31 #import <SecurityFoundation/SFSigningOperation.h>
32 #import <SecurityFoundation/SFDigestOperation.h>
33 #import <SecurityFoundation/SFKey.h>
34 #import <SecurityFoundation/SFKey_Private.h>
36 #import <corecrypto/cchkdf.h>
37 #import <corecrypto/ccsha2.h>
38 #import <corecrypto/ccec.h>
40 #include <utilities/debugging.h>
42 @interface OTBottledPeerSigned ()
43 @property (nonatomic, strong) OTBottledPeer* bp;
44 @property (nonatomic, strong) NSData* signatureUsingEscrowKey;
45 @property (nonatomic, strong) NSData* signatureUsingPeerKey;
46 @property (nonatomic, strong) NSData* escrowSigningPublicKey;
49 @implementation OTBottledPeerSigned
52 - (nullable instancetype) initWithBottledPeer:(OTBottledPeer*)bp
53 escrowedSigningKey:(SFECKeyPair *)escrowedSigningKey
54 peerSigningKey:(SFECKeyPair *)peerSigningKey
55 error:(NSError**)error
60 _escrowSigningSPKI = [escrowedSigningKey.publicKey encodeSubjectPublicKeyInfo];
61 SFEC_X962SigningOperation* xso = [OTBottledPeerSigned signingOperation];
62 _signatureUsingEscrowKey = [xso sign:bp.data withKey:escrowedSigningKey error:error].signature;
63 if (!_signatureUsingEscrowKey) {
66 _signatureUsingPeerKey = [xso sign:bp.data withKey:peerSigningKey error:error].signature;
67 if (!_signatureUsingPeerKey) {
74 -(NSString*) escrowSigningPublicKeyHash
76 const struct ccdigest_info *di = ccsha384_di();
77 NSMutableData* result = [[NSMutableData alloc] initWithLength:ccsha384_di()->output_size];
79 ccdigest(di, [self.escrowSigningPublicKey length], [self.escrowSigningPublicKey bytes], [result mutableBytes]);
81 return [result base64EncodedStringWithOptions:0];
84 // Verify signatures, or return nil
85 - (nullable instancetype) initWithBottledPeer:(OTBottledPeer*)bp
86 signatureUsingEscrow:(NSData*)signatureUsingEscrow
87 signatureUsingPeerKey:(NSData*)signatureUsingPeerKey
88 escrowedSigningPubKey:(SFECPublicKey *)escrowedSigningPubKey
89 error:(NSError**)error
94 _escrowSigningSPKI = [escrowedSigningPubKey encodeSubjectPublicKeyInfo];
95 _signatureUsingPeerKey = signatureUsingPeerKey;
96 _signatureUsingEscrowKey = signatureUsingEscrow;
97 _escrowSigningPublicKey = [escrowedSigningPubKey keyData];
99 SFEC_X962SigningOperation* xso = [OTBottledPeerSigned signingOperation];
101 SFSignedData *escrowSigned = [[SFSignedData alloc] initWithData:bp.data signature:signatureUsingEscrow];
102 if (![xso verify:escrowSigned withKey:escrowedSigningPubKey error:error]) {
105 SFSignedData *peerSigned = [[SFSignedData alloc] initWithData:bp.data signature:signatureUsingPeerKey];
106 if (![xso verify:peerSigned withKey:bp.peerSigningKey.publicKey error:error]) {
109 //stuff restored keys in the keychain
110 [OTIdentity storeOctagonIdentityIntoKeychain:self.bp.peerSigningKey restoredEncryptionKey:self.bp.peerEncryptionKey escrowSigningPubKeyHash:self.escrowSigningPublicKeyHash restoredPeerID:self.bp.spID error:error];
115 + (SFEC_X962SigningOperation*) signingOperation
117 SFECKeySpecifier *keySpecifier = [[SFECKeySpecifier alloc] initWithCurve:SFEllipticCurveNistp384];
118 id<SFDigestOperation> digestOperation = [[SFSHA384DigestOperation alloc] init];
119 return [[SFEC_X962SigningOperation alloc] initWithKeySpecifier:keySpecifier digestOperation:digestOperation];
122 + (BOOL) verifyBottleSignature:(NSData*)data signature:(NSData*)signature key:(_SFECPublicKey*) pubKey error:(NSError**)error
124 SFEC_X962SigningOperation* xso = [OTBottledPeerSigned signingOperation];
126 SFSignedData *peerSigned = [[SFSignedData alloc] initWithData:data signature:signature];
128 return ([xso verify:peerSigned withKey:pubKey error:error] != nil);
132 - (nullable instancetype) initWithBottledPeerRecord:(OTBottledPeerRecord *)record
133 escrowKeys:(OTEscrowKeys *)escrowKeys
134 error:(NSError**)error
136 OTBottledPeer *bp = [[OTBottledPeer alloc] initWithData:record.bottle
137 escrowKeys:escrowKeys
142 return [self initWithBottledPeer:bp
143 signatureUsingEscrow:record.signatureUsingEscrowKey
144 signatureUsingPeerKey:record.signatureUsingPeerKey
145 escrowedSigningPubKey:escrowKeys.signingKey.publicKey
149 - (OTBottledPeerRecord *)asRecord:(NSString*)escrowRecordID
151 OTBottledPeerRecord *rec = [[OTBottledPeerRecord alloc] init];
152 rec.spID = self.bp.spID;
153 rec.escrowRecordID = [escrowRecordID copy];
154 rec.peerSigningSPKI = [self.bp.peerSigningKey.publicKey encodeSubjectPublicKeyInfo];
155 rec.escrowedSigningSPKI = self.escrowSigningSPKI;
156 rec.bottle = self.bp.data;
157 rec.signatureUsingPeerKey = self.signatureUsingPeerKey;
158 rec.signatureUsingEscrowKey = self.signatureUsingEscrowKey;
159 rec.launched = @"NO";