Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / onlineupdate / source / libmar / verify / MacVerifyCrypto.cpp
blobe86fac3c5863f204b775f15fe59dce221604f551
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include <CoreFoundation/CoreFoundation.h>
6 #include <Security/Security.h>
7 #include <dlfcn.h>
9 #include "cryptox.h"
11 // We declare the necessary parts of the Security Transforms API here since
12 // we're building with the 10.6 SDK, which doesn't know about Security
13 // Transforms.
14 extern "C" {
15 const CFStringRef kSecTransformInputAttributeName = CFSTR("INPUT");
16 typedef CFTypeRef SecTransformRef;
17 typedef struct OpaqueSecKeyRef* SecKeyRef;
19 typedef SecTransformRef (*SecTransformCreateReadTransformWithReadStreamFunc)
20 (CFReadStreamRef inputStream);
21 SecTransformCreateReadTransformWithReadStreamFunc
22 SecTransformCreateReadTransformWithReadStreamPtr = NULL;
23 typedef CFTypeRef (*SecTransformExecuteFunc)(SecTransformRef transform,
24 CFErrorRef* error);
25 SecTransformExecuteFunc SecTransformExecutePtr = NULL;
26 typedef SecTransformRef (*SecVerifyTransformCreateFunc)(SecKeyRef key,
27 CFDataRef signature,
28 CFErrorRef* error);
29 SecVerifyTransformCreateFunc SecVerifyTransformCreatePtr = NULL;
30 typedef Boolean (*SecTransformSetAttributeFunc)(SecTransformRef transform,
31 CFStringRef key,
32 CFTypeRef value,
33 CFErrorRef* error);
34 SecTransformSetAttributeFunc SecTransformSetAttributePtr = NULL;
37 #define MAC_OS_X_VERSION_10_7_HEX 0x00001070
39 static int sOnLionOrLater = -1;
41 static bool OnLionOrLater()
43 if (sOnLionOrLater < 0) {
44 SInt32 major = 0, minor = 0;
46 CFURLRef url =
47 CFURLCreateWithString(kCFAllocatorDefault,
48 CFSTR("file:///System/Library/CoreServices/SystemVersion.plist"),
49 NULL);
50 CFReadStreamRef stream =
51 CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
52 CFReadStreamOpen(stream);
53 CFDictionaryRef sysVersionPlist = (CFDictionaryRef)
54 CFPropertyListCreateWithStream(kCFAllocatorDefault,
55 stream, 0, kCFPropertyListImmutable,
56 NULL, NULL);
57 CFReadStreamClose(stream);
58 CFRelease(stream);
59 CFRelease(url);
61 CFStringRef versionString = (CFStringRef)
62 CFDictionaryGetValue(sysVersionPlist, CFSTR("ProductVersion"));
63 CFArrayRef versions =
64 CFStringCreateArrayBySeparatingStrings(kCFAllocatorDefault,
65 versionString, CFSTR("."));
66 CFIndex count = CFArrayGetCount(versions);
67 if (count > 0) {
68 CFStringRef component = (CFStringRef) CFArrayGetValueAtIndex(versions, 0);
69 major = CFStringGetIntValue(component);
70 if (count > 1) {
71 component = (CFStringRef) CFArrayGetValueAtIndex(versions, 1);
72 minor = CFStringGetIntValue(component);
75 CFRelease(sysVersionPlist);
76 CFRelease(versions);
78 if (major < 10) {
79 sOnLionOrLater = 0;
80 } else {
81 int version = 0x1000 + (minor << 4);
82 sOnLionOrLater = version >= MAC_OS_X_VERSION_10_7_HEX ? 1 : 0;
86 return sOnLionOrLater > 0 ? true : false;
89 static bool sCssmInitialized = false;
90 static CSSM_VERSION sCssmVersion = {2, 0};
91 static const CSSM_GUID sMozCssmGuid =
92 { 0x9243121f, 0x5820, 0x4b41,
93 { 0xa6, 0x52, 0xba, 0xb6, 0x3f, 0x9d, 0x3d, 0x7f }};
94 static CSSM_CSP_HANDLE sCspHandle = CSSM_INVALID_HANDLE;
96 void* cssmMalloc (CSSM_SIZE aSize, void* aAllocRef) {
97 (void)aAllocRef;
98 return malloc(aSize);
101 void cssmFree (void* aPtr, void* aAllocRef) {
102 (void)aAllocRef;
103 free(aPtr);
104 return;
107 void* cssmRealloc (void* aPtr, CSSM_SIZE aSize, void* aAllocRef) {
108 (void)aAllocRef;
109 return realloc(aPtr, aSize);
112 void* cssmCalloc (uint32 aNum, CSSM_SIZE aSize, void* aAllocRef) {
113 (void)aAllocRef;
114 return calloc(aNum, aSize);
117 static CSSM_API_MEMORY_FUNCS cssmMemFuncs = {
118 &cssmMalloc,
119 &cssmFree,
120 &cssmRealloc,
121 &cssmCalloc,
122 NULL
125 CryptoX_Result
126 CryptoMac_InitCryptoProvider()
128 if (!OnLionOrLater()) {
129 return CryptoX_Success;
132 if (!SecTransformCreateReadTransformWithReadStreamPtr) {
133 SecTransformCreateReadTransformWithReadStreamPtr =
134 (SecTransformCreateReadTransformWithReadStreamFunc)
135 dlsym(RTLD_DEFAULT, "SecTransformCreateReadTransformWithReadStream");
137 if (!SecTransformExecutePtr) {
138 SecTransformExecutePtr = (SecTransformExecuteFunc)
139 dlsym(RTLD_DEFAULT, "SecTransformExecute");
141 if (!SecVerifyTransformCreatePtr) {
142 SecVerifyTransformCreatePtr = (SecVerifyTransformCreateFunc)
143 dlsym(RTLD_DEFAULT, "SecVerifyTransformCreate");
145 if (!SecTransformSetAttributePtr) {
146 SecTransformSetAttributePtr = (SecTransformSetAttributeFunc)
147 dlsym(RTLD_DEFAULT, "SecTransformSetAttribute");
149 if (!SecTransformCreateReadTransformWithReadStreamPtr ||
150 !SecTransformExecutePtr ||
151 !SecVerifyTransformCreatePtr ||
152 !SecTransformSetAttributePtr) {
153 return CryptoX_Error;
155 return CryptoX_Success;
158 CryptoX_Result
159 CryptoMac_VerifyBegin(CryptoX_SignatureHandle* aInputData)
161 if (!aInputData) {
162 return CryptoX_Error;
165 void* inputData = CFDataCreateMutable(kCFAllocatorDefault, 0);
166 if (!inputData) {
167 return CryptoX_Error;
170 if (!OnLionOrLater()) {
171 CSSM_DATA_PTR cssmData = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA));
172 if (!cssmData) {
173 CFRelease(inputData);
174 return CryptoX_Error;
176 cssmData->Data = (uint8*)inputData;
177 cssmData->Length = 0;
178 *aInputData = cssmData;
179 return CryptoX_Success;
182 *aInputData = inputData;
183 return CryptoX_Success;
186 CryptoX_Result
187 CryptoMac_VerifyUpdate(CryptoX_SignatureHandle* aInputData, void* aBuf,
188 unsigned int aLen)
190 if (aLen == 0) {
191 return CryptoX_Success;
193 if (!aInputData || !*aInputData) {
194 return CryptoX_Error;
197 CFMutableDataRef inputData;
198 if (!OnLionOrLater()) {
199 inputData = (CFMutableDataRef)((CSSM_DATA_PTR)*aInputData)->Data;
200 ((CSSM_DATA_PTR)*aInputData)->Length += aLen;
201 } else {
202 inputData = (CFMutableDataRef)*aInputData;
205 CFDataAppendBytes(inputData, (const uint8*)aBuf, aLen);
206 return CryptoX_Success;
209 CryptoX_Result
210 CryptoMac_LoadPublicKey(const unsigned char* aCertData,
211 unsigned int aDataSize,
212 CryptoX_PublicKey* aPublicKey)
214 if (!aCertData || aDataSize == 0 || !aPublicKey) {
215 return CryptoX_Error;
217 *aPublicKey = NULL;
219 if (!OnLionOrLater()) {
220 if (!sCspHandle) {
221 CSSM_RETURN rv;
222 if (!sCssmInitialized) {
223 CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE;
224 rv = CSSM_Init(&sCssmVersion,
225 CSSM_PRIVILEGE_SCOPE_PROCESS,
226 &sMozCssmGuid,
227 CSSM_KEY_HIERARCHY_NONE,
228 &pvcPolicy,
229 NULL);
230 if (rv != CSSM_OK) {
231 return CryptoX_Error;
233 sCssmInitialized = true;
236 rv = CSSM_ModuleLoad(&gGuidAppleCSP,
237 CSSM_KEY_HIERARCHY_NONE,
238 NULL,
239 NULL);
240 if (rv != CSSM_OK) {
241 return CryptoX_Error;
244 CSSM_CSP_HANDLE cspHandle;
245 rv = CSSM_ModuleAttach(&gGuidAppleCSP,
246 &sCssmVersion,
247 &cssmMemFuncs,
249 CSSM_SERVICE_CSP,
251 CSSM_KEY_HIERARCHY_NONE,
252 NULL,
254 NULL,
255 &cspHandle);
256 if (rv != CSSM_OK) {
257 return CryptoX_Error;
259 sCspHandle = cspHandle;
263 CFDataRef certData = CFDataCreate(kCFAllocatorDefault,
264 aCertData,
265 aDataSize);
266 if (!certData) {
267 return CryptoX_Error;
270 SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault,
271 certData);
272 CFRelease(certData);
273 if (!cert) {
274 return CryptoX_Error;
277 OSStatus status = SecCertificateCopyPublicKey(cert,
278 (SecKeyRef*)aPublicKey);
279 CFRelease(cert);
280 if (status != 0) {
281 return CryptoX_Error;
284 return CryptoX_Success;
287 CryptoX_Result
288 CryptoMac_VerifySignature(CryptoX_SignatureHandle* aInputData,
289 CryptoX_PublicKey* aPublicKey,
290 const unsigned char* aSignature,
291 unsigned int aSignatureLen)
293 if (!aInputData || !*aInputData || !aPublicKey || !*aPublicKey ||
294 !aSignature || aSignatureLen == 0) {
295 return CryptoX_Error;
298 if (!OnLionOrLater()) {
299 if (!sCspHandle) {
300 return CryptoX_Error;
303 CSSM_KEY* publicKey;
304 OSStatus status = SecKeyGetCSSMKey((SecKeyRef)*aPublicKey,
305 (const CSSM_KEY**)&publicKey);
306 if (status) {
307 return CryptoX_Error;
310 CSSM_CC_HANDLE ccHandle;
311 if (CSSM_CSP_CreateSignatureContext(sCspHandle,
312 CSSM_ALGID_SHA1WithRSA,
313 NULL,
314 publicKey,
315 &ccHandle) != CSSM_OK) {
316 return CryptoX_Error;
319 CryptoX_Result result = CryptoX_Error;
320 CSSM_DATA signatureData;
321 signatureData.Data = (uint8*)aSignature;
322 signatureData.Length = aSignatureLen;
323 CSSM_DATA inputData;
324 inputData.Data =
325 CFDataGetMutableBytePtr((CFMutableDataRef)
326 (((CSSM_DATA_PTR)*aInputData)->Data));
327 inputData.Length = ((CSSM_DATA_PTR)*aInputData)->Length;
328 if (CSSM_VerifyData(ccHandle,
329 &inputData,
331 CSSM_ALGID_NONE,
332 &signatureData) == CSSM_OK) {
333 result = CryptoX_Success;
335 return result;
338 CFDataRef signatureData = CFDataCreate(kCFAllocatorDefault,
339 aSignature, aSignatureLen);
340 if (!signatureData) {
341 return CryptoX_Error;
344 CFErrorRef error;
345 SecTransformRef verifier =
346 SecVerifyTransformCreatePtr((SecKeyRef)*aPublicKey,
347 signatureData,
348 &error);
349 if (!verifier || error) {
350 CFRelease(signatureData);
351 return CryptoX_Error;
354 SecTransformSetAttributePtr(verifier,
355 kSecTransformInputAttributeName,
356 (CFDataRef)*aInputData,
357 &error);
358 if (error) {
359 CFRelease(signatureData);
360 CFRelease(verifier);
361 return CryptoX_Error;
364 CryptoX_Result result = CryptoX_Error;
365 CFTypeRef rv = SecTransformExecutePtr(verifier, &error);
366 if (error) {
367 CFRelease(signatureData);
368 CFRelease(verifier);
369 return CryptoX_Error;
372 if (CFGetTypeID(rv) == CFBooleanGetTypeID() &&
373 CFBooleanGetValue((CFBooleanRef)rv) == true) {
374 result = CryptoX_Success;
377 CFRelease(signatureData);
378 CFRelease(verifier);
380 return result;
383 void
384 CryptoMac_FreeSignatureHandle(CryptoX_SignatureHandle* aInputData)
386 if (!aInputData || !*aInputData) {
387 return;
390 CFMutableDataRef inputData = NULL;
391 if (OnLionOrLater()) {
392 inputData = (CFMutableDataRef)*aInputData;
393 } else {
394 inputData = (CFMutableDataRef)((CSSM_DATA_PTR)*aInputData)->Data;
397 CFRelease(inputData);
398 if (!OnLionOrLater()) {
399 free((CSSM_DATA_PTR)*aInputData);
403 void
404 CryptoMac_FreePublicKey(CryptoX_PublicKey* aPublicKey)
406 if (!aPublicKey || !*aPublicKey) {
407 return;
409 if (!OnLionOrLater() && sCspHandle != CSSM_INVALID_HANDLE) {
410 CSSM_ModuleDetach(sCspHandle);
411 sCspHandle = CSSM_INVALID_HANDLE;
413 CFRelease((SecKeyRef)*aPublicKey);