snej@0
|
1 |
//
|
snej@0
|
2 |
// MYPublicKey.m
|
snej@0
|
3 |
// MYCrypto
|
snej@0
|
4 |
//
|
snej@0
|
5 |
// Created by Jens Alfke on 3/21/09.
|
snej@0
|
6 |
// Copyright 2009 Jens Alfke. All rights reserved.
|
snej@0
|
7 |
//
|
snej@0
|
8 |
|
snej@0
|
9 |
#import "MYPublicKey.h"
|
snej@0
|
10 |
#import "MYCrypto_Private.h"
|
snej@0
|
11 |
#import "MYDigest.h"
|
snej@0
|
12 |
#import "MYErrorUtils.h"
|
snej@0
|
13 |
#import <CommonCrypto/CommonDigest.h>
|
snej@0
|
14 |
|
snej@0
|
15 |
|
snej@0
|
16 |
#pragma mark -
|
snej@0
|
17 |
@implementation MYPublicKey
|
snej@0
|
18 |
|
snej@0
|
19 |
|
snej@0
|
20 |
- (void) dealloc
|
snej@0
|
21 |
{
|
snej@0
|
22 |
[_digest release];
|
snej@0
|
23 |
[super dealloc];
|
snej@0
|
24 |
}
|
snej@0
|
25 |
|
snej@0
|
26 |
- (SecExternalItemType) keyType {
|
snej@3
|
27 |
#if MYCRYPTO_USE_IPHONE_API
|
snej@3
|
28 |
return kSecAttrKeyClassPublic;
|
snej@3
|
29 |
#else
|
snej@0
|
30 |
return kSecItemTypePublicKey;
|
snej@3
|
31 |
#endif
|
snej@0
|
32 |
}
|
snej@3
|
33 |
|
snej@0
|
34 |
- (NSUInteger)hash {
|
snej@0
|
35 |
return self.publicKeyDigest.hash;
|
snej@0
|
36 |
}
|
snej@0
|
37 |
|
snej@0
|
38 |
- (NSString*) description {
|
snej@0
|
39 |
return $sprintf(@"%@[%@]", [self class], self.publicKeyDigest.abbreviatedHexString);
|
snej@0
|
40 |
}
|
snej@0
|
41 |
|
snej@0
|
42 |
- (MYSHA1Digest*) publicKeyDigest {
|
snej@0
|
43 |
if (!_digest)
|
snej@3
|
44 |
_digest = [[self _keyDigest] retain];
|
snej@0
|
45 |
return _digest;
|
snej@0
|
46 |
}
|
snej@0
|
47 |
|
snej@3
|
48 |
#if !MYCRYPTO_USE_IPHONE_API
|
snej@13
|
49 |
- (SecExternalFormat) _externalFormat {
|
snej@14
|
50 |
return kSecFormatBSAFE;
|
snej@0
|
51 |
}
|
snej@3
|
52 |
#endif
|
snej@0
|
53 |
|
snej@0
|
54 |
|
snej@13
|
55 |
- (NSData*) rawEncryptData: (NSData*)data {
|
snej@3
|
56 |
return [self _crypt: data operation: YES];
|
snej@0
|
57 |
}
|
snej@0
|
58 |
|
snej@0
|
59 |
|
snej@0
|
60 |
- (BOOL) verifySignature: (NSData*)signature ofData: (NSData*)data {
|
snej@0
|
61 |
Assert(data);
|
snej@0
|
62 |
Assert(signature);
|
snej@1
|
63 |
|
snej@3
|
64 |
#if MYCRYPTO_USE_IPHONE_API
|
snej@3
|
65 |
uint8_t digest[CC_SHA1_DIGEST_LENGTH];
|
snej@3
|
66 |
CC_SHA1(data.bytes,data.length, digest);
|
snej@3
|
67 |
OSStatus err = SecKeyRawVerify(self.keyRef, kSecPaddingPKCS1SHA1,
|
snej@3
|
68 |
digest,sizeof(digest), //data.bytes, data.length,
|
snej@3
|
69 |
signature.bytes, signature.length);
|
snej@3
|
70 |
return err==noErr;
|
snej@3
|
71 |
|
snej@3
|
72 |
#else
|
jens@17
|
73 |
CSSM_CC_HANDLE ccHandle = [self _createSignatureContext: CSSM_ALGID_SHA1WithRSA];
|
snej@0
|
74 |
if (!ccHandle) return NO;
|
snej@0
|
75 |
CSSM_DATA original = {data.length, (void*)data.bytes};
|
snej@0
|
76 |
CSSM_DATA sig = {signature.length, (void*)signature.bytes};
|
snej@0
|
77 |
CSSM_RETURN cssmErr = CSSM_VerifyData(ccHandle, &original, 1, CSSM_ALGID_NONE, &sig);
|
snej@0
|
78 |
CSSM_DeleteContext(ccHandle);
|
snej@0
|
79 |
if (cssmErr == CSSM_OK)
|
snej@0
|
80 |
return YES;
|
snej@0
|
81 |
if (cssmErr != CSSMERR_CSP_VERIFY_FAILED)
|
snej@0
|
82 |
Warn(@"CSSM error verifying signature: %u", MYErrorName(MYCSSMErrorDomain,cssmErr));
|
snej@0
|
83 |
return NO;
|
snej@3
|
84 |
#endif
|
snej@0
|
85 |
}
|
snej@0
|
86 |
|
snej@0
|
87 |
|
snej@4
|
88 |
#if !TARGET_OS_IPHONE
|
snej@4
|
89 |
- (CSSM_WRAP_KEY*) _unwrappedCSSMKey {
|
snej@4
|
90 |
const CSSM_KEY *key = self.cssmKey;
|
snej@4
|
91 |
|
snej@4
|
92 |
if (key->KeyHeader.BlobType == CSSM_KEYBLOB_WRAPPED) {
|
snej@4
|
93 |
Warn(@"Key is already wrapped.\n");
|
snej@4
|
94 |
return NULL;
|
snej@4
|
95 |
}
|
snej@4
|
96 |
|
snej@4
|
97 |
if (key->KeyHeader.KeyClass != CSSM_KEYCLASS_PUBLIC_KEY)
|
snej@4
|
98 |
Warn(@"Warning: Null wrapping a non-public key - this is a dangerous operation.\n");
|
snej@4
|
99 |
|
snej@4
|
100 |
const CSSM_ACCESS_CREDENTIALS* credentials;
|
snej@4
|
101 |
credentials = [self cssmCredentialsForOperation: CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED
|
snej@4
|
102 |
type: kSecCredentialTypeDefault error: nil];
|
snej@4
|
103 |
CSSM_CC_HANDLE ccHandle;
|
snej@4
|
104 |
if (!checkcssm(CSSM_CSP_CreateSymmetricContext(self.cssmCSPHandle,
|
snej@4
|
105 |
CSSM_ALGID_NONE, CSSM_ALGMODE_WRAP,
|
snej@4
|
106 |
NULL, NULL, NULL,
|
snej@4
|
107 |
CSSM_PADDING_NONE, NULL,
|
snej@4
|
108 |
&ccHandle),
|
snej@4
|
109 |
@"CSSM_CSP_CreateSymmetricContext"))
|
snej@4
|
110 |
return NULL;
|
snej@4
|
111 |
|
snej@4
|
112 |
CSSM_WRAP_KEY *result = malloc(sizeof(CSSM_WRAP_KEY));
|
snej@4
|
113 |
if (!checkcssm(CSSM_WrapKey(ccHandle, credentials, key, NULL, result),
|
snej@4
|
114 |
@"CSSM_WrapKey")) {
|
snej@4
|
115 |
free(result);
|
snej@4
|
116 |
result = NULL;
|
snej@4
|
117 |
}
|
snej@4
|
118 |
CSSM_DeleteContext(ccHandle);
|
snej@4
|
119 |
return result;
|
snej@4
|
120 |
}
|
snej@13
|
121 |
|
snej@13
|
122 |
|
snej@13
|
123 |
- (NSData*) wrapSessionKey: (MYSymmetricKey*)sessionKey {
|
snej@13
|
124 |
const CSSM_ACCESS_CREDENTIALS* credentials;
|
snej@13
|
125 |
credentials = [self cssmCredentialsForOperation: CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED
|
snej@13
|
126 |
type: kSecCredentialTypeDefault error: nil];
|
snej@13
|
127 |
CSSM_CSP_HANDLE cspHandle = self.cssmCSPHandle;
|
snej@13
|
128 |
CSSM_CC_HANDLE ctx;
|
snej@13
|
129 |
if (!checkcssm(CSSM_CSP_CreateAsymmetricContext(cspHandle,
|
snej@13
|
130 |
self.cssmAlgorithm,
|
snej@13
|
131 |
credentials,
|
snej@13
|
132 |
self.cssmKey,
|
snej@13
|
133 |
CSSM_PADDING_PKCS1,
|
snej@13
|
134 |
&ctx),
|
snej@13
|
135 |
@"CSSM_CSP_CreateAsymmetricContext"))
|
snej@13
|
136 |
return nil;
|
snej@14
|
137 |
|
snej@13
|
138 |
// Now wrap the key:
|
snej@13
|
139 |
NSData *result = nil;
|
snej@13
|
140 |
CSSM_WRAP_KEY wrappedKey = {};
|
snej@14
|
141 |
CSSM_DATA descriptiveData = {};
|
snej@14
|
142 |
if (checkcssm(CSSM_WrapKey(ctx, credentials, sessionKey.cssmKey, &descriptiveData, &wrappedKey),
|
snej@13
|
143 |
@"CSSM_WrapKey")) {
|
snej@13
|
144 |
// ...and copy the wrapped key data to the result NSData:
|
snej@13
|
145 |
result = [NSData dataWithBytes: wrappedKey.KeyData.Data length: wrappedKey.KeyData.Length];
|
snej@13
|
146 |
CSSM_FreeKey(cspHandle, credentials, &wrappedKey, NO);
|
snej@13
|
147 |
}
|
snej@13
|
148 |
// Finally, delete the context
|
snej@13
|
149 |
CSSM_DeleteContext(ctx);
|
snej@13
|
150 |
return result;
|
snej@13
|
151 |
}
|
snej@13
|
152 |
|
snej@13
|
153 |
|
snej@4
|
154 |
#endif
|
snej@4
|
155 |
|
snej@4
|
156 |
|
snej@0
|
157 |
@end
|
snej@0
|
158 |
|
snej@0
|
159 |
|
snej@0
|
160 |
|
snej@0
|
161 |
/*
|
snej@0
|
162 |
Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
|
snej@0
|
163 |
|
snej@0
|
164 |
Redistribution and use in source and binary forms, with or without modification, are permitted
|
snej@0
|
165 |
provided that the following conditions are met:
|
snej@0
|
166 |
|
snej@0
|
167 |
* Redistributions of source code must retain the above copyright notice, this list of conditions
|
snej@0
|
168 |
and the following disclaimer.
|
snej@0
|
169 |
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
snej@0
|
170 |
and the following disclaimer in the documentation and/or other materials provided with the
|
snej@0
|
171 |
distribution.
|
snej@0
|
172 |
|
snej@0
|
173 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
snej@0
|
174 |
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
snej@0
|
175 |
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
|
snej@0
|
176 |
BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
snej@0
|
177 |
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
snej@0
|
178 |
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
snej@0
|
179 |
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
snej@0
|
180 |
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
snej@0
|
181 |
*/
|