2014-04-08 18:06:56 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#include <CoreFoundation/CoreFoundation.h>
|
|
|
|
#include <Security/Security.h>
|
|
|
|
#include <dlfcn.h>
|
|
|
|
|
|
|
|
#include "cryptox.h"
|
|
|
|
|
|
|
|
// We declare the necessary parts of the Security Transforms API here since
|
|
|
|
// we're building with the 10.6 SDK, which doesn't know about Security
|
|
|
|
// Transforms.
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
const CFStringRef kSecTransformInputAttributeName = CFSTR("INPUT");
|
|
|
|
typedef CFTypeRef SecTransformRef;
|
|
|
|
typedef struct OpaqueSecKeyRef* SecKeyRef;
|
|
|
|
|
|
|
|
typedef SecTransformRef (*SecTransformCreateReadTransformWithReadStreamFunc)
|
|
|
|
(CFReadStreamRef inputStream);
|
|
|
|
SecTransformCreateReadTransformWithReadStreamFunc
|
|
|
|
SecTransformCreateReadTransformWithReadStreamPtr = NULL;
|
|
|
|
typedef CFTypeRef (*SecTransformExecuteFunc)(SecTransformRef transform,
|
|
|
|
CFErrorRef* error);
|
|
|
|
SecTransformExecuteFunc SecTransformExecutePtr = NULL;
|
|
|
|
typedef SecTransformRef (*SecVerifyTransformCreateFunc)(SecKeyRef key,
|
|
|
|
CFDataRef signature,
|
|
|
|
CFErrorRef* error);
|
|
|
|
SecVerifyTransformCreateFunc SecVerifyTransformCreatePtr = NULL;
|
|
|
|
typedef Boolean (*SecTransformSetAttributeFunc)(SecTransformRef transform,
|
|
|
|
CFStringRef key,
|
|
|
|
CFTypeRef value,
|
|
|
|
CFErrorRef* error);
|
|
|
|
SecTransformSetAttributeFunc SecTransformSetAttributePtr = NULL;
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
CryptoX_Result
|
|
|
|
CryptoMac_InitCryptoProvider()
|
|
|
|
{
|
|
|
|
if (!SecTransformCreateReadTransformWithReadStreamPtr) {
|
|
|
|
SecTransformCreateReadTransformWithReadStreamPtr =
|
|
|
|
(SecTransformCreateReadTransformWithReadStreamFunc)
|
|
|
|
dlsym(RTLD_DEFAULT, "SecTransformCreateReadTransformWithReadStream");
|
|
|
|
}
|
|
|
|
if (!SecTransformExecutePtr) {
|
|
|
|
SecTransformExecutePtr = (SecTransformExecuteFunc)
|
|
|
|
dlsym(RTLD_DEFAULT, "SecTransformExecute");
|
|
|
|
}
|
|
|
|
if (!SecVerifyTransformCreatePtr) {
|
|
|
|
SecVerifyTransformCreatePtr = (SecVerifyTransformCreateFunc)
|
|
|
|
dlsym(RTLD_DEFAULT, "SecVerifyTransformCreate");
|
|
|
|
}
|
|
|
|
if (!SecTransformSetAttributePtr) {
|
|
|
|
SecTransformSetAttributePtr = (SecTransformSetAttributeFunc)
|
|
|
|
dlsym(RTLD_DEFAULT, "SecTransformSetAttribute");
|
|
|
|
}
|
|
|
|
if (!SecTransformCreateReadTransformWithReadStreamPtr ||
|
|
|
|
!SecTransformExecutePtr ||
|
|
|
|
!SecVerifyTransformCreatePtr ||
|
2014-04-23 04:45:59 +04:00
|
|
|
!SecTransformSetAttributePtr) {
|
2014-04-08 18:06:56 +04:00
|
|
|
return CryptoX_Error;
|
|
|
|
}
|
|
|
|
return CryptoX_Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
CryptoX_Result
|
2014-04-23 04:45:59 +04:00
|
|
|
CryptoMac_VerifyBegin(CryptoX_SignatureHandle* aInputData)
|
2014-04-08 18:06:56 +04:00
|
|
|
{
|
2014-04-23 04:45:59 +04:00
|
|
|
if (!aInputData) {
|
|
|
|
return CryptoX_Error;
|
2014-04-08 18:06:56 +04:00
|
|
|
}
|
|
|
|
|
2014-04-23 04:45:59 +04:00
|
|
|
void* inputData = CFDataCreateMutable(kCFAllocatorDefault, 0);
|
|
|
|
if (!inputData) {
|
2014-04-08 18:06:56 +04:00
|
|
|
return CryptoX_Error;
|
|
|
|
}
|
|
|
|
|
2014-04-23 04:45:59 +04:00
|
|
|
*aInputData = inputData;
|
|
|
|
return CryptoX_Success;
|
2014-04-08 18:06:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
CryptoX_Result
|
|
|
|
CryptoMac_VerifyUpdate(CryptoX_SignatureHandle* aInputData, void* aBuf,
|
|
|
|
unsigned int aLen)
|
|
|
|
{
|
|
|
|
if (aLen == 0) {
|
|
|
|
return CryptoX_Success;
|
|
|
|
}
|
|
|
|
if (!aInputData || !*aInputData) {
|
|
|
|
return CryptoX_Error;
|
|
|
|
}
|
|
|
|
|
2016-07-23 01:29:04 +03:00
|
|
|
CFMutableDataRef inputData = (CFMutableDataRef)*aInputData;
|
2014-04-08 18:06:56 +04:00
|
|
|
|
2014-04-23 04:45:59 +04:00
|
|
|
CFDataAppendBytes(inputData, (const uint8*)aBuf, aLen);
|
|
|
|
return CryptoX_Success;
|
2014-04-08 18:06:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
CryptoX_Result
|
|
|
|
CryptoMac_LoadPublicKey(const unsigned char* aCertData,
|
2014-10-23 05:52:54 +04:00
|
|
|
unsigned int aDataSize,
|
2014-04-23 04:45:59 +04:00
|
|
|
CryptoX_PublicKey* aPublicKey)
|
2014-04-08 18:06:56 +04:00
|
|
|
{
|
2014-10-23 05:52:54 +04:00
|
|
|
if (!aCertData || aDataSize == 0 || !aPublicKey) {
|
2014-04-08 18:06:56 +04:00
|
|
|
return CryptoX_Error;
|
|
|
|
}
|
2014-04-23 04:45:59 +04:00
|
|
|
*aPublicKey = NULL;
|
2014-10-23 05:52:54 +04:00
|
|
|
CFDataRef certData = CFDataCreate(kCFAllocatorDefault,
|
|
|
|
aCertData,
|
|
|
|
aDataSize);
|
|
|
|
if (!certData) {
|
2014-04-08 18:06:56 +04:00
|
|
|
return CryptoX_Error;
|
|
|
|
}
|
|
|
|
|
2014-04-23 04:45:59 +04:00
|
|
|
SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault,
|
2014-10-23 05:52:54 +04:00
|
|
|
certData);
|
|
|
|
CFRelease(certData);
|
2014-04-08 18:06:56 +04:00
|
|
|
if (!cert) {
|
|
|
|
return CryptoX_Error;
|
|
|
|
}
|
|
|
|
|
2014-04-23 04:45:59 +04:00
|
|
|
OSStatus status = SecCertificateCopyPublicKey(cert,
|
|
|
|
(SecKeyRef*)aPublicKey);
|
2014-04-08 18:06:56 +04:00
|
|
|
CFRelease(cert);
|
2014-10-23 05:52:54 +04:00
|
|
|
if (status != 0) {
|
|
|
|
return CryptoX_Error;
|
|
|
|
}
|
2014-04-08 18:06:56 +04:00
|
|
|
|
2014-10-23 05:52:54 +04:00
|
|
|
return CryptoX_Success;
|
2014-04-08 18:06:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
CryptoX_Result
|
|
|
|
CryptoMac_VerifySignature(CryptoX_SignatureHandle* aInputData,
|
|
|
|
CryptoX_PublicKey* aPublicKey,
|
|
|
|
const unsigned char* aSignature,
|
|
|
|
unsigned int aSignatureLen)
|
|
|
|
{
|
|
|
|
if (!aInputData || !*aInputData || !aPublicKey || !*aPublicKey ||
|
|
|
|
!aSignature || aSignatureLen == 0) {
|
|
|
|
return CryptoX_Error;
|
|
|
|
}
|
|
|
|
|
|
|
|
CFDataRef signatureData = CFDataCreate(kCFAllocatorDefault,
|
|
|
|
aSignature, aSignatureLen);
|
|
|
|
if (!signatureData) {
|
|
|
|
return CryptoX_Error;
|
|
|
|
}
|
|
|
|
|
|
|
|
CFErrorRef error;
|
|
|
|
SecTransformRef verifier =
|
|
|
|
SecVerifyTransformCreatePtr((SecKeyRef)*aPublicKey,
|
|
|
|
signatureData,
|
|
|
|
&error);
|
|
|
|
if (!verifier || error) {
|
2017-07-31 09:27:27 +03:00
|
|
|
if (error) {
|
|
|
|
CFRelease(error);
|
|
|
|
}
|
2014-04-08 18:06:56 +04:00
|
|
|
CFRelease(signatureData);
|
|
|
|
return CryptoX_Error;
|
|
|
|
}
|
|
|
|
|
2017-07-31 09:27:27 +03:00
|
|
|
SecTransformSetAttributePtr(verifier,
|
|
|
|
kSecDigestTypeAttribute,
|
|
|
|
kSecDigestSHA2,
|
|
|
|
&error);
|
|
|
|
if (error) {
|
|
|
|
CFRelease(error);
|
|
|
|
CFRelease(signatureData);
|
|
|
|
CFRelease(verifier);
|
|
|
|
return CryptoX_Error;
|
|
|
|
}
|
|
|
|
|
|
|
|
int digestLength = 384;
|
|
|
|
CFNumberRef dLen = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &digestLength);
|
|
|
|
SecTransformSetAttributePtr(verifier,
|
|
|
|
kSecDigestLengthAttribute,
|
|
|
|
dLen,
|
|
|
|
&error);
|
|
|
|
CFRelease(dLen);
|
|
|
|
if (error) {
|
|
|
|
CFRelease(error);
|
|
|
|
CFRelease(signatureData);
|
|
|
|
CFRelease(verifier);
|
|
|
|
return CryptoX_Error;
|
|
|
|
}
|
|
|
|
|
2014-04-08 18:06:56 +04:00
|
|
|
SecTransformSetAttributePtr(verifier,
|
|
|
|
kSecTransformInputAttributeName,
|
|
|
|
(CFDataRef)*aInputData,
|
|
|
|
&error);
|
|
|
|
if (error) {
|
2017-07-31 09:27:27 +03:00
|
|
|
CFRelease(error);
|
2014-04-08 18:06:56 +04:00
|
|
|
CFRelease(signatureData);
|
|
|
|
CFRelease(verifier);
|
|
|
|
return CryptoX_Error;
|
|
|
|
}
|
|
|
|
|
|
|
|
CryptoX_Result result = CryptoX_Error;
|
|
|
|
CFTypeRef rv = SecTransformExecutePtr(verifier, &error);
|
|
|
|
if (error) {
|
2017-07-31 09:27:27 +03:00
|
|
|
CFRelease(error);
|
2014-04-08 18:06:56 +04:00
|
|
|
CFRelease(signatureData);
|
|
|
|
CFRelease(verifier);
|
|
|
|
return CryptoX_Error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CFGetTypeID(rv) == CFBooleanGetTypeID() &&
|
|
|
|
CFBooleanGetValue((CFBooleanRef)rv) == true) {
|
|
|
|
result = CryptoX_Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
CFRelease(signatureData);
|
|
|
|
CFRelease(verifier);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CryptoMac_FreeSignatureHandle(CryptoX_SignatureHandle* aInputData)
|
|
|
|
{
|
|
|
|
if (!aInputData || !*aInputData) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-04-23 04:45:59 +04:00
|
|
|
CFMutableDataRef inputData = NULL;
|
2016-07-23 01:29:04 +03:00
|
|
|
inputData = (CFMutableDataRef)*aInputData;
|
2014-04-08 18:06:56 +04:00
|
|
|
|
2014-04-23 04:45:59 +04:00
|
|
|
CFRelease(inputData);
|
2014-04-08 18:06:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-04-23 04:45:59 +04:00
|
|
|
CryptoMac_FreePublicKey(CryptoX_PublicKey* aPublicKey)
|
2014-04-08 18:06:56 +04:00
|
|
|
{
|
2014-04-23 04:45:59 +04:00
|
|
|
if (!aPublicKey || !*aPublicKey) {
|
2014-04-08 18:06:56 +04:00
|
|
|
return;
|
|
|
|
}
|
2016-07-23 01:29:04 +03:00
|
|
|
|
2014-04-23 04:45:59 +04:00
|
|
|
CFRelease((SecKeyRef)*aPublicKey);
|
2014-04-08 18:06:56 +04:00
|
|
|
}
|