-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCSSMPubKeyDecrypt.m
More file actions
140 lines (119 loc) · 3.65 KB
/
CSSMPubKeyDecrypt.m
File metadata and controls
140 lines (119 loc) · 3.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//
// CSSMPubKeyDecrypt.m
// PubKeyDecrypt
//
// Created by Karsten Kusche on 18.04.14.
// Copyright (c) 2014 briksoftware.com. All rights reserved.
//
#import "CSSMPubKeyDecrypt.h"
// CSSM is deprecated but has to be used if the functionality is missing in Security.framework (says the documentation)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
@implementation CSSMPubKeyDecrypt
+ (NSData*)decryptData:(NSData*)data usingPublicKey:(SecKeyRef)key error:(NSError**)error
{
CSSMPubKeyDecrypt* decrypter = [[self alloc] init];
NSData* resultData = [decrypter decryptData:data usingPublicKey:key error:error];
[decrypter release];
return resultData;
}
- (CSSM_RETURN)cryptHandleForCsp:(CSSM_CSP_HANDLE) cspHandle
key:(const CSSM_KEY*) key
into:(CSSM_CC_HANDLE*) ccHandle
{
CSSM_RETURN cssmReturn;
CSSM_CC_HANDLE ccHand = 0;
CSSM_ACCESS_CREDENTIALS credentials;
memset(&credentials, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
cssmReturn = CSSM_CSP_CreateAsymmetricContext(cspHandle,
key->KeyHeader.AlgorithmId,
&credentials, // access
key,
CSSM_PADDING_PKCS1,
&ccHand);
if(cssmReturn) {
return cssmReturn;
}
*ccHandle = ccHand;
return CSSM_OK;
}
- (CSSM_RETURN) decryptData:(const CSSM_DATA*) encryptedData
forCsp:(CSSM_CSP_HANDLE) cspHandle
key:(const CSSM_KEY*) key
into:(CSSM_DATA*) outData
{
CSSM_RETURN cssmReturn;
CSSM_CC_HANDLE ccHandle;
CSSM_DATA remData = {0, NULL};
CSSM_SIZE bytesDecrypted;
cssmReturn = [self cryptHandleForCsp:cspHandle key:key into:&ccHandle];
if (cssmReturn)
{
return cssmReturn;
}
CSSM_CONTEXT_ATTRIBUTE attribute = {};
attribute.AttributeType = CSSM_ATTRIBUTE_MODE;
attribute.AttributeLength = sizeof(UInt32);
attribute.Attribute.Uint32 = CSSM_ALGMODE_PUBLIC_KEY;
cssmReturn = CSSM_UpdateContextAttributes(ccHandle, 1, &attribute);
if (cssmReturn)
{
return cssmReturn;
}
outData->Length = 0;
outData->Data = NULL;
cssmReturn = CSSM_DecryptData(ccHandle,
encryptedData,
1,
outData,
1,
&bytesDecrypted,
&remData);
CSSM_DeleteContext(ccHandle);
if(cssmReturn)
{
return cssmReturn;
}
outData->Length = bytesDecrypted;
if(remData.Length != 0) {
/* append remaining data to plainText */
CSSM_SIZE newLen = outData->Length + remData.Length;
outData->Data = (uint8 *)realloc(outData->Data,newLen);
memmove(outData->Data + outData->Length,
remData.Data, remData.Length);
outData->Length = newLen;
free(remData.Data);
}
return CSSM_OK;
}
- (NSData*)decryptData:(NSData*)data usingPublicKey:(SecKeyRef)key error:(NSError**)errorPtr
{
const CSSM_KEY* cssm_key = nil;
CSSM_CSP_HANDLE cspHandle;
SecKeyGetCSSMKey(key, &cssm_key);
SecKeyGetCSPHandle(key, &cspHandle);
CSSM_DATA inData = {};
inData.Data = (uint8_t*)[data bytes];
inData.Length = [data length];
CSSM_DATA outData = {};
CSSM_RETURN returnValue = [self decryptData:&inData forCsp:cspHandle key:cssm_key into:&outData];
if (returnValue)
{
extern char* cssmErrorString(CSSM_RETURN errCode);
NSError* error = [NSError errorWithDomain:[NSString stringWithUTF8String:cssmErrorString(returnValue)]
code:returnValue
userInfo:nil];
if (errorPtr)
{
*errorPtr = error;
}
else
{
NSLog(@"Error in %@: %@",self,error);
}
return nil;
}
return [NSData dataWithBytesNoCopy:outData.Data length:outData.Length freeWhenDone:YES];
}
@end
#pragma clang diagnostic pop