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; }
CSSM_KEYATTR_FLAGS ConvertArrayToKeyAttributes(SecKeyRef aKey, CFArrayRef keyAttrs) { CSSM_KEYATTR_FLAGS result = CSSM_KEYATTR_RETURN_DEFAULT; if (aKey) { const CSSM_KEY* cssmKey = NULL; if (errSecSuccess == SecKeyGetCSSMKey(aKey, &cssmKey)) result = cssmKey->KeyHeader.KeyAttr; } if (!keyAttrs) return result; CFMutableArrayRef attrs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); CFIndex idx, count = CFArrayGetCount(keyAttrs); for (idx=0; idx<count; idx++) { CFTypeRef attr = (CFTypeRef) CFArrayGetValueAtIndex(keyAttrs, idx); if (attr && (CFNumberGetTypeID() == CFGetTypeID(attr))) { // Convert numeric CSSM keyattr values to equivalent attribute constants uint32 value; if (CFNumberGetValue((CFNumberRef)attr, kCFNumberSInt32Type, &value)) { switch (value) { case CSSM_KEYATTR_SENSITIVE: attr = kSecAttrIsSensitive; break; case CSSM_KEYATTR_EXTRACTABLE: attr = kSecAttrIsExtractable; break; case CSSM_KEYATTR_PERMANENT: attr = kSecAttrIsPermanent; break; default: attr = NULL; break; } } } if (attr) CFArrayAppendValue(attrs, attr); } // Set key attribute flag in result if present in the array, otherwise clear ToggleKeyAttribute(attrs, kSecAttrIsSensitive, CSSM_KEYATTR_SENSITIVE, result); ToggleKeyAttribute(attrs, kSecAttrIsExtractable, CSSM_KEYATTR_EXTRACTABLE, result); ToggleKeyAttribute(attrs, kSecAttrIsPermanent, CSSM_KEYATTR_PERMANENT, result); // if caller specified an attributes array which omitted kSecAttrIsExtractable, // this implies the sensitive attribute; force it on so that at least one bit // is set. If our result is 0, this is indistinguishable from the case where // no key attributes were specified, causing a default bitmask to be used // in subsequent import code. if (0==(result & CSSM_KEYATTR_EXTRACTABLE)) result |= CSSM_KEYATTR_SENSITIVE; CFRelease(attrs); return result; }
OSStatus cmsNullWrapKey(SecKeyRef refKey, CSSM_KEY_PTR rawKey) { CSSM_DATA descData = {0, 0}; CSSM_RETURN crtn; CSSM_CC_HANDLE ccHand; CSSM_ACCESS_CREDENTIALS creds; CSSM_CSP_HANDLE refCspHand = CSSM_INVALID_HANDLE; const CSSM_KEY *cssmKey = NULL; uint32 keyAttr; memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); memset(rawKey, 0, sizeof(CSSM_KEY)); crtn = SecKeyGetCSSMKey(refKey, &cssmKey); if(crtn) { CSSM_PERROR("SecKeyGetCSSMKey", crtn); goto loser; } crtn = SecKeyGetCSPHandle(refKey, &refCspHand); if(crtn) { CSSM_PERROR("SecKeyGetCSPHandle", crtn); goto loser; } crtn = CSSM_CSP_CreateSymmetricContext(refCspHand, CSSM_ALGID_NONE, CSSM_ALGMODE_NONE, &creds, NULL, // unwrappingKey NULL, // initVector CSSM_PADDING_NONE, 0, // Params &ccHand); if(crtn) { CSSM_PERROR("CSSM_CSP_CreateSymmetricContext", crtn); return crtn; } keyAttr = rawKey->KeyHeader.KeyAttr; keyAttr &= ~(CSSM_KEYATTR_ALWAYS_SENSITIVE | CSSM_KEYATTR_NEVER_EXTRACTABLE | CSSM_KEYATTR_MODIFIABLE); keyAttr |= CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; crtn = CSSM_WrapKey(ccHand, &creds, cssmKey, &descData, rawKey); if(crtn != CSSM_OK) { CSSM_PERROR("CSSM_WrapKey", crtn); } CSSM_DeleteContext(ccHand); loser: return crtn; }
void SecCmsContentInfoSetBulkKey(SecCmsContentInfoRef cinfo, SecSymmetricKeyRef bulkkey) { const CSSM_KEY *cssmKey = NULL; cinfo->bulkkey = bulkkey; CFRetain(cinfo->bulkkey); SecKeyGetCSSMKey(cinfo->bulkkey, &cssmKey); cinfo->keysize = cssmKey ? cssmKey->KeyHeader.LogicalKeySizeInBits : 0; }
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; }
/* encrypt something with a public key */ static int pubKeyEncrypt( SecKeyRef pubKeyRef) { const CSSM_KEY *cssmKey; OSStatus ortn; CSSM_CSP_HANDLE cspHand; ortn = SecKeyGetCSSMKey(pubKeyRef, &cssmKey); if(ortn) { cssmPerror("SecKeyGetCSSMKey", ortn); return -1; } ortn = SecKeyGetCSPHandle(pubKeyRef, &cspHand); if(ortn) { cssmPerror("SecKeyGetCSPHandle", ortn); return -1; } char *ptext = "something to encrypt"; CSSM_DATA ptextData = {strlen(ptext), (uint8 *)ptext}; CSSM_DATA ctextData = { 0, NULL }; CSSM_RETURN crtn; crtn = cspEncrypt(cspHand, CSSM_ALGID_RSA, 0, CSSM_PADDING_PKCS1, // mode/pad cssmKey, NULL, 0, 0, // effect/rounds NULL, // IV &ptextData, &ctextData, CSSM_FALSE); if(crtn) { return -1; } /* slighyly hazardous, allocated by CSPDL's allocator */ free(ctextData.Data); return 0; }
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; }
static int testExtractable( SecKeychainRef keychain, Boolean extractable, Boolean explicit) { OSStatus status; SecKeyRef publicKeyRef = NULL; SecKeyRef privateKeyRef = NULL; CFStringRef label = (extractable) ? CFSTR("test-extractable-YES") : CFSTR("test-extractable-NO"); Boolean *extractablePtr = (explicit) ? &extractable : NULL; status = GenerateRSAKeyPair(keychain, label, 1024, // size extractablePtr, &publicKeyRef, &privateKeyRef); if (status != noErr) { //errx(EXIT_FAILURE, "Unable to get key pair (err = %d)", status); return status; } // check that the attributes of the generated private key are what we think they are const CSSM_KEY *cssmPrivKey; status = SecKeyGetCSSMKey(privateKeyRef, &cssmPrivKey); ok_status(status, "%s: SecKeyGetCSSMKey", testName); if (status != noErr) { //errx(EXIT_FAILURE, "Unable to get CSSM reference key (err = %d)", status); return status; } if (extractable) { ok(cssmPrivKey->KeyHeader.KeyAttr & CSSM_KEYATTR_EXTRACTABLE, "%s: check private key marked as extractable (as requested)", testName); if (!(cssmPrivKey->KeyHeader.KeyAttr & CSSM_KEYATTR_EXTRACTABLE)) { //errx(EXIT_FAILURE, "Oops! the private key was not marked as extractable!"); return 1; } } else { ok(!(cssmPrivKey->KeyHeader.KeyAttr & CSSM_KEYATTR_EXTRACTABLE), "%s: check private key marked as non-extractable (as requested)", testName); if (cssmPrivKey->KeyHeader.KeyAttr & CSSM_KEYATTR_EXTRACTABLE) { //errx(EXIT_FAILURE, "Oops! the private key was marked as extractable!"); return 1; } } SecKeyImportExportParameters keyParams; memset(&keyParams, 0, sizeof(keyParams)); keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; keyParams.passphrase = CFSTR("borken"); CFDataRef exportedData = NULL; status = SecKeychainItemExport(privateKeyRef, kSecFormatWrappedPKCS8, 0, &keyParams, &exportedData); if(extractable) { ok_status(status, "%s: SecKeychainItemExport (PKCS8) (and we expected it to succeed)", testName); } else { is(status, errSecDataNotAvailable, "%s: SecKeychainItemExport (PKCS8) (and we expected this to fail with errSecDataNotAvailable)", testName); } status = SecKeychainItemExport(privateKeyRef, kSecFormatPKCS12, 0, &keyParams, &exportedData); if(extractable) { ok_status(status, "%s: SecKeychainItemExport(and we expected it to succeed)", testName); } else { is(status, errSecDataNotAvailable, "%s: SecKeychainItemExport (PKCS12) (and we expected this to fail with errSecDataNotAvailable)", testName); } if (status != noErr) { if (extractable) { //errx(EXIT_FAILURE, "Unable to export extractable key! (err = %d)", status); return 1; } else { status = 0; // wasn't extractable, so this is the expected result } } else if (status == noErr && !extractable) { //errx(EXIT_FAILURE, "Was able to export non-extractable key! (err = %d)", status); return 1; } status = SecKeychainItemDelete((SecKeychainItemRef)publicKeyRef); ok_status(status, "%s: SecKeychainItemDelete", testName); if (status != noErr) { warnx("Unable to delete created public key from keychain (err = %d)", (int)status); } status = SecKeychainItemDelete((SecKeychainItemRef)privateKeyRef); ok_status(status, "%s: SecKeychainItemDelete", testName); if (status != noErr) { warnx("Unable to delete created private key from keychain (err = %d)", (int)status); } CFRelease(publicKeyRef); CFRelease(privateKeyRef); return 0; }
/* * Encrypt/Decrypt */ OSStatus sslRsaEncrypt( SSLContext *ctx, SSLPubKey *pubKey, const uint32_t padding, const uint8_t *plainText, size_t plainTextLen, uint8_t *cipherText, // mallocd by caller; RETURNED size_t cipherTextLen, // available size_t *actualBytes) // RETURNED { #if 0 gi_uint16 giCipherTextLen = cipherTextLen; RSAStatus rsaStatus; assert(actualBytes != NULL); rsaStatus = RSA_Encrypt(&pubKey->rsaKey, RP_PKCS1, getRandomByte, plainText, plainTextLen, cipherText, &giCipherTextLen); *actualBytes = giCipherTextLen; return rsaStatus ? rsaStatusToSSL(rsaStatus) : noErr; #else size_t ctlen = cipherTextLen; assert(actualBytes != NULL); #if RSA_PUB_KEY_USAGE_HACK /* Force key usage to allow encryption with public key */ #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) const CSSM_KEY_PTR cssmKey = NULL; if (SecKeyGetCSSMKey(SECKEYREF(pubKey), &cssmKey)==noErr && cssmKey) cssmKey->KeyHeader.KeyUsage |= CSSM_KEYUSE_ENCRYPT; #endif #endif OSStatus status = SecKeyEncrypt(SECKEYREF(pubKey), padding, plainText, plainTextLen, cipherText, &ctlen); if (status) { sslErrorLog("sslRsaEncrypt: SecKeyEncrypt failed (error %d)\n", status); } /* Since the KeyExchange already allocated modulus size bytes we'll use all of them. SecureTransport has always sent that many bytes, so we're not going to deviate, to avoid interoperability issues. */ if (!status && (ctlen < cipherTextLen)) { size_t offset = cipherTextLen - ctlen; memmove(cipherText + offset, cipherText, ctlen); memset(cipherText, 0, offset); ctlen = cipherTextLen; } if (actualBytes) *actualBytes = ctlen; if (status) sslErrorLog("***sslRsaEncrypt: error %d\n", status); return status; #endif }
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; }
void P12Coder::addSecKey( SecKeyRef keyRef) { /* get the cert's attrs (not data) */ /* * Convert the attr name strings we happen to know about to * unknowable name-as-int values. */ UInt32 printNameTag; OSStatus ortn = attrNameToInt(P12_KEY_ATTR_PRINT_NAME, &printNameTag); if(ortn) { p12ErrorLog("addSecKey: problem looking up key attr name\n"); MacOSError::throwMe(ortn); } UInt32 labelHashTag; ortn = attrNameToInt(P12_KEY_ATTR_LABEL_AND_HASH, &labelHashTag); if(ortn) { p12ErrorLog("addSecKey: problem looking up key attr name\n"); MacOSError::throwMe(ortn); } UInt32 tags[2]; tags[0] = printNameTag; tags[1] = labelHashTag; /* I don't know what the format field is for */ SecKeychainAttributeInfo attrInfo; attrInfo.count = 2; attrInfo.tag = tags; attrInfo.format = NULL; // ??? /* FIXME header says this is an IN/OUT param, but it's not */ SecKeychainAttributeList *attrList = NULL; ortn = SecKeychainItemCopyAttributesAndData( (SecKeychainItemRef)keyRef, &attrInfo, NULL, // itemClass &attrList, NULL, // don't need the data NULL); if(ortn) { p12ErrorLog("addSecKey: SecKeychainItemCopyAttributesAndData " "error\n"); MacOSError::throwMe(ortn); } /* Snag the attrs, convert to something useful */ CFStringRef friendName = NULL; CFDataRef localKeyId = NULL; for(unsigned i=0; i<attrList->count; i++) { SecKeychainAttribute *attr = &attrList->attr[i]; if(attr->tag == printNameTag) { friendName = CFStringCreateWithBytes(NULL, (UInt8 *)attr->data, attr->length, kCFStringEncodingUTF8, false); } else if(attr->tag == labelHashTag) { localKeyId = CFDataCreate(NULL, (UInt8 *)attr->data, attr->length); } else { p12ErrorLog("addSecKey: unexpected attr tag\n"); MacOSError::throwMe(errSecParam); } } /* * Infer the CSP associated with this key. * FIXME: this should be an attribute of the SecKeyRef itself, * not inferred from the keychain it happens to be living on * (SecKeyRefs should not have to be attached to Keychains at * this point). */ SecKeychainRef kcRef; ortn = SecKeychainItemCopyKeychain((SecKeychainItemRef)keyRef, &kcRef); if(ortn) { p12ErrorLog("addSecKey: SecKeychainItemCopyKeychain returned %d\n", (int)ortn); MacOSError::throwMe(ortn); } CSSM_CSP_HANDLE cspHand; ortn = SecKeychainGetCSPHandle(kcRef, &cspHand); if(ortn) { p12ErrorLog("addSecKey: SecKeychainGetCSPHandle returned %d\n", (int)ortn); MacOSError::throwMe(ortn); } CFRelease(kcRef); /* and the CSSM_KEY itself */ const CSSM_KEY *cssmKey; ortn = SecKeyGetCSSMKey(keyRef, &cssmKey); if(ortn) { p12ErrorLog("addSecKey: SecKeyGetCSSMKey returned %d\n", (int)ortn); MacOSError::throwMe(ortn); } /* Cook up a key bag and save it */ P12KeyBag *keyBag = new P12KeyBag(cssmKey, cspHand, friendName, localKeyId, NULL, // other attrs mCoder, keyRef); addKey(keyBag); SecKeychainItemFreeAttributesAndData(attrList, NULL); if(friendName) { CFRelease(friendName); } if(localKeyId) { CFRelease(localKeyId); } }
static SecCmsCipherContext * SecCmsCipherContextStart(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorithmID *algid, PRBool encrypt) { SecCmsCipherContext *cc; CSSM_CC_HANDLE ciphercc = 0; SECOidData *oidData; SECOidTag algtag; CSSM_ALGORITHMS algorithm; CSSM_PADDING padding = CSSM_PADDING_PKCS7; CSSM_ENCRYPT_MODE mode; CSSM_CSP_HANDLE cspHandle; const CSSM_KEY *cssmKey; OSStatus rv; uint8 ivbuf[8]; CSSM_DATA initVector = { sizeof(ivbuf), ivbuf }; //CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_ALG_PARAMS, sizeof(CSSM_DATA_PTR) }; rv = SecKeyGetCSPHandle(key, &cspHandle); if (rv) goto loser; rv = SecKeyGetCSSMKey(key, &cssmKey); if (rv) goto loser; // @@@ Add support for PBE based stuff oidData = SECOID_FindOID(&algid->algorithm); if (!oidData) goto loser; algtag = oidData->offset; algorithm = oidData->cssmAlgorithm; if (!algorithm) goto loser; switch (algtag) { case SEC_OID_RC2_CBC: case SEC_OID_RC4: case SEC_OID_DES_EDE3_CBC: case SEC_OID_DES_EDE: case SEC_OID_DES_CBC: case SEC_OID_RC5_CBC_PAD: case SEC_OID_AES_128_CBC: case SEC_OID_AES_192_CBC: case SEC_OID_AES_256_CBC: case SEC_OID_FORTEZZA_SKIPJACK: mode = CSSM_ALGMODE_CBCPadIV8; break; case SEC_OID_DES_ECB: case SEC_OID_AES_128_ECB: case SEC_OID_AES_192_ECB: case SEC_OID_AES_256_ECB: mode = CSSM_ALGMODE_ECBPad; break; case SEC_OID_DES_OFB: mode = CSSM_ALGMODE_OFBPadIV8; break; case SEC_OID_DES_CFB: mode = CSSM_ALGMODE_CFBPadIV8; break; default: goto loser; } if (encrypt) { CSSM_CC_HANDLE randomcc; //SECItem *parameters; // Generate random initVector if (CSSM_CSP_CreateRandomGenContext(cspHandle, CSSM_ALGID_APPLE_YARROW, NULL, /* seed*/ initVector.Length, &randomcc)) goto loser; if (CSSM_GenerateRandom(randomcc, &initVector)) goto loser; CSSM_DeleteContext(randomcc); // Put IV into algid.parameters switch (algtag) { case SEC_OID_RC4: case SEC_OID_DES_EDE3_CBC: case SEC_OID_DES_EDE: case SEC_OID_DES_CBC: case SEC_OID_AES_128_CBC: case SEC_OID_AES_192_CBC: case SEC_OID_AES_256_CBC: case SEC_OID_FORTEZZA_SKIPJACK: case SEC_OID_DES_ECB: case SEC_OID_AES_128_ECB: case SEC_OID_AES_192_ECB: case SEC_OID_AES_256_ECB: case SEC_OID_DES_OFB: case SEC_OID_DES_CFB: /* Just encode the initVector as an octet string. */ if (!SEC_ASN1EncodeItem(poolp, &algid->parameters, &initVector, SEC_OctetStringTemplate)) goto loser; break; case SEC_OID_RC2_CBC: { sec_rc2cbcParameter rc2 = {}; unsigned long rc2version; SECItem *newParams; rc2.iv = initVector; rc2version = rc2_unmap(cssmKey->KeyHeader.LogicalKeySizeInBits); if (!SEC_ASN1EncodeUnsignedInteger (NULL, &(rc2.rc2ParameterVersion), rc2version)) goto loser; newParams = SEC_ASN1EncodeItem (poolp, &algid->parameters, &rc2, sec_rc2cbc_parameter_template); PORT_Free(rc2.rc2ParameterVersion.Data); if (newParams == NULL) goto loser; break; } case SEC_OID_RC5_CBC_PAD: default: // @@@ Implement rc5 params stuff. goto loser; break; } } else { // Extract IV from algid.parameters // Put IV into algid.parameters switch (algtag) { case SEC_OID_RC4: case SEC_OID_DES_EDE3_CBC: case SEC_OID_DES_EDE: case SEC_OID_DES_CBC: case SEC_OID_AES_128_CBC: case SEC_OID_AES_192_CBC: case SEC_OID_AES_256_CBC: case SEC_OID_FORTEZZA_SKIPJACK: case SEC_OID_DES_ECB: case SEC_OID_AES_128_ECB: case SEC_OID_AES_192_ECB: case SEC_OID_AES_256_ECB: case SEC_OID_DES_OFB: case SEC_OID_DES_CFB: { CSSM_DATA iv = {}; /* Just decode the initVector from an octet string. */ rv = SEC_ASN1DecodeItem(NULL, &iv, SEC_OctetStringTemplate, &(algid->parameters)); if (rv) goto loser; if (initVector.Length != iv.Length) { PORT_Free(iv.Data); goto loser; } memcpy(initVector.Data, iv.Data, initVector.Length); PORT_Free(iv.Data); break; } case SEC_OID_RC2_CBC: { sec_rc2cbcParameter rc2 = {}; unsigned long ulEffectiveBits; rv = SEC_ASN1DecodeItem(NULL, &rc2 ,sec_rc2cbc_parameter_template, &(algid->parameters)); if (rv) goto loser; if (initVector.Length != rc2.iv.Length) { PORT_Free(rc2.iv.Data); PORT_Free(rc2.rc2ParameterVersion.Data); goto loser; } memcpy(initVector.Data, rc2.iv.Data, initVector.Length); PORT_Free(rc2.iv.Data); ulEffectiveBits = rc2_map(&rc2.rc2ParameterVersion); PORT_Free(rc2.rc2ParameterVersion.Data); if (ulEffectiveBits != cssmKey->KeyHeader.LogicalKeySizeInBits) goto loser; break; } case SEC_OID_RC5_CBC_PAD: default: // @@@ Implement rc5 params stuff. goto loser; break; } } if (CSSM_CSP_CreateSymmetricContext(cspHandle, algorithm, mode, NULL, /* accessCred */ cssmKey, &initVector, padding, NULL, /* reserved */ &ciphercc)) goto loser; if (encrypt) rv = CSSM_EncryptDataInit(ciphercc); else rv = CSSM_DecryptDataInit(ciphercc); if (rv) goto loser; cc = (SecCmsCipherContext *)PORT_ZAlloc(sizeof(SecCmsCipherContext)); if (cc == NULL) goto loser; cc->cc = ciphercc; cc->encrypt = encrypt; return cc; loser: if (ciphercc) CSSM_DeleteContext(ciphercc); return NULL; }
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; } if (!OnLionOrLater()) { if (!sCspHandle) { return CryptoX_Error; } CSSM_KEY* publicKey; OSStatus status = SecKeyGetCSSMKey((SecKeyRef)*aPublicKey, (const CSSM_KEY**)&publicKey); if (status) { return CryptoX_Error; } CSSM_CC_HANDLE ccHandle; if (CSSM_CSP_CreateSignatureContext(sCspHandle, CSSM_ALGID_SHA1WithRSA, NULL, publicKey, &ccHandle) != CSSM_OK) { return CryptoX_Error; } CryptoX_Result result = CryptoX_Error; CSSM_DATA signatureData; signatureData.Data = (uint8*)aSignature; signatureData.Length = aSignatureLen; CSSM_DATA inputData; inputData.Data = CFDataGetMutableBytePtr((CFMutableDataRef) (((CSSM_DATA_PTR)*aInputData)->Data)); inputData.Length = ((CSSM_DATA_PTR)*aInputData)->Length; if (CSSM_VerifyData(ccHandle, &inputData, 1, CSSM_ALGID_NONE, &signatureData) == CSSM_OK) { result = CryptoX_Success; } return result; } CFDataRef signatureData = CFDataCreate(kCFAllocatorDefault, aSignature, aSignatureLen); if (!signatureData) { return CryptoX_Error; } CFErrorRef error; SecTransformRef verifier = SecVerifyTransformCreatePtr((SecKeyRef)*aPublicKey, signatureData, &error); if (!verifier || error) { CFRelease(signatureData); return CryptoX_Error; } SecTransformSetAttributePtr(verifier, kSecTransformInputAttributeName, (CFDataRef)*aInputData, &error); if (error) { CFRelease(signatureData); CFRelease(verifier); return CryptoX_Error; } CryptoX_Result result = CryptoX_Error; CFTypeRef rv = SecTransformExecutePtr(verifier, &error); if (error) { CFRelease(signatureData); CFRelease(verifier); return CryptoX_Error; } if (CFGetTypeID(rv) == CFBooleanGetTypeID() && CFBooleanGetValue((CFBooleanRef)rv) == true) { result = CryptoX_Success; } CFRelease(signatureData); CFRelease(verifier); return result; }