static int kc_rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA * rsa, int padding) { struct kc_rsa *kc = RSA_get_app_data(rsa); CSSM_RETURN cret; OSStatus ret; const CSSM_ACCESS_CREDENTIALS *creds; SecKeyRef privKeyRef = kc->pkey; CSSM_CSP_HANDLE cspHandle; const CSSM_KEY *cssmKey; CSSM_CC_HANDLE handle = 0; CSSM_DATA out, in, rem; int fret = 0; CSSM_SIZE outlen = 0; char remdata[1024]; if (padding != RSA_PKCS1_PADDING) return -1; cret = SecKeyGetCSSMKey(privKeyRef, &cssmKey); if(cret) heim_abort("SecKeyGetCSSMKey failed: %d", (int)cret); cret = SecKeyGetCSPHandle(privKeyRef, &cspHandle); if(cret) heim_abort("SecKeyGetCSPHandle failed: %d", (int)cret); ret = SecKeyGetCredentials(privKeyRef, CSSM_ACL_AUTHORIZATION_DECRYPT, kSecCredentialTypeNoUI, &creds); if(ret) heim_abort("SecKeyGetCredentials failed: %d", (int)ret); ret = CSSM_CSP_CreateAsymmetricContext (cspHandle, CSSM_ALGID_RSA, creds, cssmKey, CSSM_PADDING_PKCS1, &handle); if(ret) heim_abort("CSSM_CSP_CreateAsymmetricContext failed: %d", (int)ret); in.Data = (uint8 *)from; in.Length = flen; out.Data = (uint8 *)to; out.Length = kc->keysize; rem.Data = (uint8 *)remdata; rem.Length = sizeof(remdata); cret = CSSM_DecryptData(handle, &in, 1, &out, 1, &outlen, &rem); if(cret) { /* cssmErrorString(cret); */ fret = -1; } else fret = (int)out.Length; if(handle) CSSM_DeleteContext(handle); return fret; }
static int kc_rsa_private_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { struct kc_rsa *kc = RSA_get_app_data(rsa); CSSM_RETURN cret; OSStatus ret; const CSSM_ACCESS_CREDENTIALS *creds; SecKeyRef privKeyRef = (SecKeyRef)kc->item; CSSM_CSP_HANDLE cspHandle; const CSSM_KEY *cssmKey; CSSM_CC_HANDLE sigHandle = 0; CSSM_DATA sig, in; int fret = 0; if (padding != RSA_PKCS1_PADDING) return -1; cret = SecKeyGetCSSMKey(privKeyRef, &cssmKey); if(cret) abort(); cret = SecKeyGetCSPHandle(privKeyRef, &cspHandle); if(cret) abort(); ret = SecKeyGetCredentials(privKeyRef, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeDefault, &creds); if(ret) abort(); ret = CSSM_CSP_CreateSignatureContext(cspHandle, CSSM_ALGID_RSA, creds, cssmKey, &sigHandle); if(ret) abort(); in.Data = (uint8 *)from; in.Length = flen; sig.Data = (uint8 *)to; sig.Length = kc->keysize; cret = CSSM_SignData(sigHandle, &in, 1, CSSM_ALGID_NONE, &sig); if(cret) { /* cssmErrorString(cret); */ fret = -1; } else fret = sig.Length; if(sigHandle) CSSM_DeleteContext(sigHandle); return fret; }
CFDataRef decodePrivateKeyHeader(SecKeychainRef keychain, const FVPrivateKeyHeader &inHeader) { // kSecKeyLabel is defined in libsecurity_keychain/lib/SecKey.h SecKeychainAttribute attrs[] = { { 6 /* kSecKeyLabel */, inHeader.publicKeyHashSize, const_cast<uint8 *>(inHeader.publicKeyHash) } }; SecKeychainAttributeList attrList = { sizeof(attrs) / sizeof(SecKeychainAttribute), attrs }; CSSM_CSP_HANDLE cspHandle = 0; const CSSM_KEY *cssmKey = NULL; const CSSM_ACCESS_CREDENTIALS *accessCred = NULL; CSSM_CC_HANDLE cc = 0; SecKeychainSearchRef _searchRef; throwIfError(SecKeychainSearchCreateFromAttributes(keychain, (SecItemClass) CSSM_DL_DB_RECORD_PRIVATE_KEY, &attrList, &_searchRef)); CFRef<SecKeychainSearchRef> searchRef(_searchRef); SecKeychainItemRef _item; if (SecKeychainSearchCopyNext(searchRef, &_item) != 0) { return NULL; // XXX possibly should throw here? } CFRef<SecKeyRef> keyItem(reinterpret_cast<SecKeyRef>(_item)); throwIfError(SecKeyGetCSPHandle(keyItem, &cspHandle)); throwIfError(SecKeyGetCSSMKey(keyItem, &cssmKey)); throwIfError(SecKeyGetCredentials(keyItem, CSSM_ACL_AUTHORIZATION_DECRYPT, kSecCredentialTypeDefault, &accessCred)); throwIfError(CSSM_CSP_CreateAsymmetricContext(cspHandle, cssmKey->KeyHeader.AlgorithmId, accessCred, cssmKey, CSSM_PADDING_PKCS1, &cc)); CFDataRef result; try { CssmMemoryFunctions memFuncs; throwIfError(CSSM_GetAPIMemoryFunctions(cspHandle, &memFuncs)); CssmMemoryFunctionsAllocator allocator(memFuncs); const CssmData cipherBuf(const_cast<uint8 *>(inHeader.encryptedBlob), inHeader.encryptedBlobSize); CssmAutoData clearBuf(allocator); CssmAutoData remData(allocator); size_t bytesDecrypted; CSSM_RETURN crx = CSSM_DecryptData(cc, &cipherBuf, 1, &clearBuf.get(), 1, &bytesDecrypted, &remData.get()); secinfo("FDERecovery", "decodePrivateKeyHeader: CSSM_DecryptData result: %d", crx); throwIfError(crx); // throwIfError(CSSM_DecryptData(cc, &cipherBuf, 1, &clearBuf.get(), 1, &bytesDecrypted, &remData.get())); clearBuf.length(bytesDecrypted); // rawKey.copy(clearBuf.get()); result = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)clearBuf.get().data(), clearBuf.get().length()); // result = parseKeyBlob(clearBuf.get()); } catch(...) { CSSM_DeleteContext(cc); throw; } throwIfError(CSSM_DeleteContext(cc)); return result; }
SECStatus ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf, PRBool isTLS, KeyType keyType) { SECStatus rv = SECFailure; PRBool doDerEncode = PR_FALSE; unsigned int signatureLen; OSStatus status = noErr; CSSM_CSP_HANDLE cspHandle = 0; const CSSM_KEY *cssmKey = NULL; CSSM_ALGORITHMS sigAlg; CSSM_ALGORITHMS digestAlg; const CSSM_ACCESS_CREDENTIALS * cssmCreds = NULL; CSSM_RETURN cssmRv; CSSM_DATA hashData; CSSM_DATA signatureData; CSSM_CC_HANDLE cssmSignature = 0; const SSL3Opaque* prefix; unsigned int prefixLen; SSL3Opaque prefixAndHash[SSL_MAX_DIGEST_INFO_PREFIX + HASH_LENGTH_MAX]; buf->data = NULL; status = SecKeyGetCSPHandle(key, &cspHandle); if (status != noErr) { PORT_SetError(SEC_ERROR_INVALID_KEY); goto done; } status = SecKeyGetCSSMKey(key, &cssmKey); if (status != noErr || !cssmKey) { PORT_SetError(SEC_ERROR_NO_KEY); goto done; } /* SecKeyGetBlockSize wasn't addeded until OS X 10.6 - but the * needed information is readily available on the key itself. */ signatureLen = (cssmKey->KeyHeader.LogicalKeySizeInBits + 7) / 8; if (signatureLen == 0) { PORT_SetError(SEC_ERROR_INVALID_KEY); goto done; } buf->data = (unsigned char *)PORT_Alloc(signatureLen); if (!buf->data) goto done; /* error code was set. */ sigAlg = cssmKey->KeyHeader.AlgorithmId; digestAlg = CSSM_ALGID_NONE; switch (keyType) { case rsaKey: PORT_Assert(sigAlg == CSSM_ALGID_RSA); if (ssl3_GetDigestInfoPrefix(hash->hashAlg, &prefix, &prefixLen) != SECSuccess) { goto done; } if (prefixLen + hash->len > sizeof(prefixAndHash)) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); goto done; } memcpy(prefixAndHash, prefix, prefixLen); memcpy(prefixAndHash + prefixLen, hash->u.raw, hash->len); hashData.Data = prefixAndHash; hashData.Length = prefixLen + hash->len; break; case dsaKey: case ecKey: if (keyType == ecKey) { PORT_Assert(sigAlg == CSSM_ALGID_ECDSA); doDerEncode = PR_TRUE; } else { PORT_Assert(sigAlg == CSSM_ALGID_DSA); doDerEncode = isTLS; } if (hash->hashAlg == SEC_OID_UNKNOWN) { hashData.Data = hash->u.s.sha; hashData.Length = sizeof(hash->u.s.sha); } else { hashData.Data = hash->u.raw; hashData.Length = hash->len; } break; default: PORT_SetError(SEC_ERROR_INVALID_KEY); goto done; } PRINT_BUF(60, (NULL, "hash(es) to be signed", hashData.Data, hashData.Length)); /* TODO(rsleevi): Should it be kSecCredentialTypeNoUI? In Win32, at least, * you can prevent the UI by setting the provider handle on the * certificate to be opened with CRYPT_SILENT, but is there an equivalent? */ status = SecKeyGetCredentials(key, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeDefault, &cssmCreds); if (status != noErr) { PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, status); goto done; } signatureData.Length = signatureLen; signatureData.Data = (uint8*)buf->data; cssmRv = CSSM_CSP_CreateSignatureContext(cspHandle, sigAlg, cssmCreds, cssmKey, &cssmSignature); if (cssmRv) { PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, cssmRv); goto done; } /* See "Apple Cryptographic Service Provider Functional Specification" */ if (cssmKey->KeyHeader.AlgorithmId == CSSM_ALGID_RSA) { /* To set RSA blinding for RSA keys */ CSSM_CONTEXT_ATTRIBUTE blindingAttr; blindingAttr.AttributeType = CSSM_ATTRIBUTE_RSA_BLINDING; blindingAttr.AttributeLength = sizeof(uint32); blindingAttr.Attribute.Uint32 = 1; cssmRv = CSSM_UpdateContextAttributes(cssmSignature, 1, &blindingAttr); if (cssmRv) { PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, cssmRv); goto done; } } cssmRv = CSSM_SignData(cssmSignature, &hashData, 1, digestAlg, &signatureData); if (cssmRv) { PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, cssmRv); goto done; } buf->len = signatureData.Length; if (doDerEncode) { SECItem derSig = {siBuffer, NULL, 0}; /* This also works for an ECDSA signature */ rv = DSAU_EncodeDerSigWithLen(&derSig, buf, buf->len); if (rv == SECSuccess) { PORT_Free(buf->data); /* discard unencoded signature. */ *buf = derSig; /* give caller encoded signature. */ } else if (derSig.data) { PORT_Free(derSig.data); } } else { rv = SECSuccess; } PRINT_BUF(60, (NULL, "signed hashes", buf->data, buf->len)); done: /* cspHandle, cssmKey, and cssmCreds are owned by the SecKeyRef and * should not be freed. When the PlatformKey is freed, they will be * released. */ if (cssmSignature) CSSM_DeleteContext(cssmSignature); if (rv != SECSuccess && buf->data) { PORT_Free(buf->data); buf->data = NULL; } return rv; }
static int kc_rsa_sign(int type, const unsigned char *from, unsigned int flen, unsigned char *to, unsigned int *tlen, const RSA *rsa) { struct kc_rsa *kc = RSA_get_app_data(rk_UNCONST(rsa)); CSSM_RETURN cret; OSStatus ret; const CSSM_ACCESS_CREDENTIALS *creds; SecKeyRef privKeyRef = kc->pkey; CSSM_CSP_HANDLE cspHandle; const CSSM_KEY *cssmKey; CSSM_CC_HANDLE sigHandle = 0; CSSM_DATA sig, in; int fret = 0; CSSM_ALGORITHMS stype; if (type == NID_md5) { stype = CSSM_ALGID_MD5; } else if (type == NID_sha1) { stype = CSSM_ALGID_SHA1; } else if (type == NID_sha256) { stype = CSSM_ALGID_SHA256; } else if (type == NID_sha384) { stype = CSSM_ALGID_SHA384; } else if (type == NID_sha512) { stype = CSSM_ALGID_SHA512; } else return -1; cret = SecKeyGetCSSMKey(privKeyRef, &cssmKey); if(cret) heim_abort("SecKeyGetCSSMKey failed: %d", cret); cret = SecKeyGetCSPHandle(privKeyRef, &cspHandle); if(cret) heim_abort("SecKeyGetCSPHandle failed: %d", cret); ret = SecKeyGetCredentials(privKeyRef, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeNoUI, &creds); if(ret) heim_abort("SecKeyGetCredentials failed: %d", (int)ret); ret = CSSM_CSP_CreateSignatureContext(cspHandle, CSSM_ALGID_RSA, creds, cssmKey, &sigHandle); if(ret) heim_abort("CSSM_CSP_CreateSignatureContext failed: %d", (int)ret); in.Data = (uint8 *)from; in.Length = flen; sig.Data = (uint8 *)to; sig.Length = kc->keysize; cret = CSSM_SignData(sigHandle, &in, 1, stype, &sig); if(cret) { /* cssmErrorString(cret); */ fret = -1; } else { fret = 1; *tlen = (unsigned int)sig.Length; } if(sigHandle) CSSM_DeleteContext(sigHandle); return fret; }