//
// Find and store database objects (primitive layer)
//
bool CodeSignatures::find(Identity &id, uid_t user)
{
	if (id.mState != Identity::untried)
		return id.mState == Identity::valid;
	try {
		DbKey userKey('H', id.getHash(), true, user);
		CssmData linkValue;
		if (mDb.get(userKey, linkValue)) {
			id.mName = string(linkValue.interpretedAs<const char>(), linkValue.length());
			IFDUMPING("equiv", id.debugDump("found/user"));
			id.mState = Identity::valid;
			return true;
		}
		DbKey sysKey('H', id.getHash());
		if (mDb.get(sysKey, linkValue)) {
			id.mName = string(linkValue.interpretedAs<const char>(), linkValue.length());
			IFDUMPING("equiv", id.debugDump("found/system"));
			id.mState = Identity::valid;
			return true;
		}
	} catch (...) {
		secdebug("codesign", "exception validating identity for %s - marking failed", id.path().c_str());
		id.mState = Identity::invalid;
	}
	return id.mState == Identity::valid;
}
//
// Generation stuff.
//
void
SDCSPSession::GenerateRandom(CSSM_CC_HANDLE ccHandle,
							 const Context &context,
							 CssmData &randomNumber)
{
    checkOperation(context.type(), CSSM_ALGCLASS_RANDOMGEN);
	// if (context.algorithm() != @@@) CssmError::throwMe(ALGORITHM_NOT_SUPPORTED);
	uint32 needed = context.getInt(CSSM_ATTRIBUTE_OUTPUT_SIZE, CSSMERR_CSP_MISSING_ATTR_OUTPUT_SIZE);

	// @@@ What about the seed?
    if (randomNumber.length())
	{
        if (randomNumber.length() < needed)
            CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
		clientSession().generateRandom(context, randomNumber);
    }
	else
	{
        randomNumber.Data = alloc<uint8>(needed);
		try
		{
			clientSession().generateRandom(context, randomNumber);
		}
		catch(...)
		{
			free(randomNumber.Data);
			randomNumber.Data = NULL;
			throw;
		}
	}
}
void CSPFullPluginSession::Writer::allocate(size_t needed, Allocator &alloc)
{
	if (!needed)
		return; // No output buffer space needed so we're done.
    else if (vec == firstVec && !*vec) {	// initial null vector element, wants allocation there
        *vec = makeBuffer(needed, alloc);
        lastVec = vec;		// ignore all subsequent buffers in vector
		useData(vec);
    } else {
        // how much output space do we have left?
        size_t size = currentSize;
        for (CssmData *v = vec + 1; v <= lastVec; v++)
            size += v->length();
        if (size >= needed)
            return;	// we're fine
        if (remData) {
            if (!*remData) {	        // have overflow, can allocate
                *remData = makeBuffer(needed - size, alloc);
                return;	// got it
            }
            if (size + remData->length() >= needed)
                return;	// will fit into overflow
        }
        // not enough buffer space, and can't allocate
        CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
    }
}
void CL_certCrlDecodeComponents(
	const CssmData 	&signedItem,		// DER-encoded cert or CRL
	CssmOwnedData	&tbsBlob,			// still DER-encoded
	CssmOwnedData	&algId,				// ditto
	CssmOwnedData	&rawSig)			// raw bits (not an encoded AsnBits)
{
	/* BER-decode into temp memory */
	NSS_SignedCertOrCRL nssObj;
	SecNssCoder coder;
	PRErrorCode prtn;
	
	memset(&nssObj, 0, sizeof(nssObj));
	prtn = coder.decode(signedItem.data(), signedItem.length(),
		kSecAsn1SignedCertOrCRLTemplate, &nssObj);
	if(prtn) {
		CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
	}
	
	/* tbsBlob and algId are raw ASN_ANY including tags, which we pass 
	 * back to caller intact */
	tbsBlob.copy(nssObj.tbsBlob.Data, nssObj.tbsBlob.Length);
	algId.copy(nssObj.signatureAlgorithm.Data, 
		nssObj.signatureAlgorithm.Length);
		
	/* signature is a bit string which we do in fact decode */
	rawSig.copy(nssObj.signature.Data,
		(nssObj.signature.Length + 7) / 8);
}
void KCEventNotifier::PostKeychainEvent(SecKeychainEvent whichEvent,
										const DLDbIdentifier &dlDbIdentifier, 
										const PrimaryKey &primaryKey)
{
	NameValueDictionary nvd;

	Endian<pid_t> thePid = getpid();
	nvd.Insert (new NameValuePair (PID_KEY, CssmData (reinterpret_cast<void*>(&thePid), sizeof (pid_t))));

	if (dlDbIdentifier)
	{
		NameValueDictionary::MakeNameValueDictionaryFromDLDbIdentifier (dlDbIdentifier, nvd);
	}

	CssmData* pKey = primaryKey;
	
    if (primaryKey)
    {
		nvd.Insert (new NameValuePair (ITEM_KEY, *pKey));
    }

	// flatten the dictionary
	CssmData data;
	nvd.Export (data);
	
	SecurityServer::ClientSession cs (Allocator::standard(), Allocator::standard());
	cs.postNotification (SecurityServer::kNotificationDomainDatabase, whichEvent, data);

    secdebug("kcnotify", "KCEventNotifier::PostKeychainEvent posted event %u", (unsigned int) whichEvent);

	free (data.data ());
}
Beispiel #6
0
//
// Nonthrowing passphrase-based unlock. This returns false if unlock failed.
// Note that this requires an explicitly given passphrase.
// Caller must hold common lock.
//
bool KeychainDatabase::decode(const CssmData &passphrase)
{
	assert(mBlob);
	common().setup(mBlob, passphrase);
	bool success = decode();
    if (success) {
        if (common().isLoginKeychain() && (unlock_keybag(common(), passphrase.data(), (int)passphrase.length()) != 0)) {
            service_context_t context = common().session().get_current_service_context();
            // check to see if it was locked with the master key if so change the secret to the passphrase
            if (!common().session().keybagGetState(session_keybag_check_master_key)) {

                CssmAutoData key(Allocator::standard(Allocator::sensitive));
                key = common().masterKey()->keyData();
                if (service_client_kb_unlock(&context, key.data(), (int)key.length()) == 0) {
                    service_client_kb_change_secret(&context, key.data(), (int)key.length(), passphrase.data(), (int)passphrase.length());
                }
                common().session().keybagSetState(session_keybag_check_master_key);
            }

            bool no_pin = false;
            if (service_client_kb_is_locked(&context, NULL, &no_pin) == 0) {
                if ((passphrase.length() > 0) && no_pin) {
                    syslog(LOG_ERR, "Updating passphrase for your iCloud keychain");
                    service_client_kb_change_secret(&context, NULL, 0, passphrase.data(), (int)passphrase.length());
                } else {
                    syslog(LOG_ERR, "The passphrase for your login.keychain and your iCloud keychain are out of sync");
                }
            }
        }
    }
    return success;
}
//
// Conversion from/to OID strings.
// These are not strict; invalid inputs are not necessarily flagged as errors.
//
static unsigned long getOid(const CssmData &data, unsigned int &pos)
{
	unsigned long q = 0;
	do {
		q = q * 128 + (data.byte(pos) & ~0x80);
	} while (pos < data.length() && data.byte(pos++) & 0x80);
	return q;
}
Beispiel #8
0
bool UnixDb::put(const CssmData &key, const CssmData &value, int flags)
{
	Data dKey(key);
	Data dValue(value);
	int rc = mDb->put(mDb, &dKey, &dValue, flags);
	secdebug("unixdb", "put(%p,[:%ld],[:%ld],flags=0x%x)=%d",
		mDb, key.length(), value.length(), flags, rc);
	checkError(rc);
	return !rc;
}
/*
 * Generate keygen parameters, stash them in a context attr array for later use
 * when actually generating the keys.
 */
void DSAKeyPairGenContext::generate(
	const Context &context, 
	uint32 bitSize,
    CssmData &params,
    uint32 &attrCount, 
	Context::Attr * &attrs)
{
	void *seed = NULL;
	unsigned seedLen = 0;

	/* optional seed from context */
	CssmData *seedData = context.get<CssmData>(CSSM_ATTRIBUTE_SEED);
	if(seedData) {
		seed = seedData->data();
		seedLen = (unsigned)seedData->length();
	}

	/* generate the params, temp alloc from SecNssCoder  */
	NSS_DSAAlgParams algParams;
	SecNssCoder coder;
	dsaGenParams(bitSize, seed, seedLen, algParams, coder);
	
	/*
	 * Here comes the fun part. 
	 * We "return" the DER encoding of these generated params in two ways:
	 * 1. Copy out to app via the params argument, mallocing if Data ptr is NULL.
	 *    The app must free this. 
	 * 2. Cook up a 1-element Context::attr array containing one ALG_PARAM attr,
	 *    a CSSM_DATA_PTR containing the DER encoding. We have to save a ptr to
	 *    this attr array and free it, the CSSM_DATA it points to, and the DER
	 *    encoding *that* points to, in our destructor. 
	 *
	 * First, DER encode.
	 */
	CssmAutoData aDerData(session());
	DSAEncodeAlgParams(algParams, aDerData);

	/* copy/release that into a mallocd CSSM_DATA. */
	CSSM_DATA_PTR derData = (CSSM_DATA_PTR)session().malloc(sizeof(CSSM_DATA));
	*derData = aDerData.release();
	
	/* stuff that into a one-element Attr array which we keep after returning */
	freeGenAttrs();
	mGenAttrs = (Context::Attr *)session().malloc(sizeof(Context::Attr));
	mGenAttrs->AttributeType   = CSSM_ATTRIBUTE_ALG_PARAMS;
	mGenAttrs->AttributeLength = sizeof(CSSM_DATA);
	mGenAttrs->Attribute.Data  = derData;

	/* and "return" this stuff */
	copyCssmData(CssmData::overlay(*derData), params, session());
	attrCount = 1;
	attrs = mGenAttrs;
}
void Policy::setValue(const CssmData &value)
{
	StLock<Mutex>_(mMutex);
	mValue = value;
	mAuxValue.reset();

	// Certain policy values may contain an embedded pointer. Ask me how I feel about that.
	if (mOid == CSSMOID_APPLE_TP_SSL ||
		mOid == CSSMOID_APPLE_TP_EAP ||
		mOid == CSSMOID_APPLE_TP_IP_SEC ||
		mOid == CSSMOID_APPLE_TP_APPLEID_SHARING)
	{
		CSSM_APPLE_TP_SSL_OPTIONS *opts = (CSSM_APPLE_TP_SSL_OPTIONS *)value.data();
		if (opts->Version == CSSM_APPLE_TP_SSL_OPTS_VERSION)
		{
			if (opts->ServerNameLen > 0)
			{
				// Copy auxiliary data, then update the embedded pointer to reference our copy
				mAuxValue.copy(const_cast<char*>(opts->ServerName), opts->ServerNameLen);
				mValue.get().interpretedAs<CSSM_APPLE_TP_SSL_OPTIONS>()->ServerName =
					reinterpret_cast<char*>(mAuxValue.data());
			}
			else
			{
				// Clear the embedded pointer!
				mValue.get().interpretedAs<CSSM_APPLE_TP_SSL_OPTIONS>()->ServerName =
					reinterpret_cast<char*>(NULL);
			}
		}
	}
	else if (mOid == CSSMOID_APPLE_TP_SMIME ||
			mOid == CSSMOID_APPLE_TP_ICHAT ||
			mOid == CSSMOID_APPLE_TP_PASSBOOK_SIGNING)
	{
		CSSM_APPLE_TP_SMIME_OPTIONS *opts = (CSSM_APPLE_TP_SMIME_OPTIONS *)value.data();
		if (opts->Version == CSSM_APPLE_TP_SMIME_OPTS_VERSION)
		{
			if (opts->SenderEmailLen > 0)
			{
				// Copy auxiliary data, then update the embedded pointer to reference our copy
				mAuxValue.copy(const_cast<char*>(opts->SenderEmail), opts->SenderEmailLen);
				mValue.get().interpretedAs<CSSM_APPLE_TP_SMIME_OPTIONS>()->SenderEmail =
					reinterpret_cast<char*>(mAuxValue.data());
			}
			else
			{
				// Clear the embedded pointer!
				mValue.get().interpretedAs<CSSM_APPLE_TP_SMIME_OPTIONS>()->SenderEmail =
					reinterpret_cast<char*>(NULL);
			}
		}
	}
}
DbKey::DbKey(char type, const CssmData &key, bool perUser, uid_t user)
	: CssmAutoData(Allocator::standard())
{
	using namespace LowLevelMemoryUtilities;
	char header[20];
	size_t headerLength;
	if (perUser)
		headerLength = 1 + sprintf(header, "%c%d", type, user);
	else
		headerLength = 1 + sprintf(header, "%cS", type);
	malloc(headerLength + key.length());
	memcpy(this->data(), header, headerLength);
	memcpy(get().at(headerLength), key.data(), key.length());
}
/* one-shot constructor, decoding from DER-encoded data */
DecodedCert::DecodedCert(
	AppleX509CLSession	&session,
	const CssmData 	&encodedCert)
	: DecodedItem(session)
{
	memset(&mCert, 0, sizeof(mCert));
	PRErrorCode prtn = mCoder.decode(encodedCert.data(), encodedCert.length(), 
		kSecAsn1SignedCertTemplate, &mCert);
	if(prtn) {
		CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
	}
	mDecodedExtensions.decodeFromNss(mCert.tbs.extensions);
	mState = IS_DecodedAll;
}
Beispiel #13
0
bool UnixDb::get(const CssmData &key, CssmData &value, int flags) const
{
	Data dKey(key);
	Data val;
	int rc = mDb->get(mDb, &dKey, &val, flags);
	secdebug("unixdb", "get(%p,[:%ld],flags=0x%x)=%d[:%ld]",
		mDb, key.length(), flags, rc, value.length());
	checkError(rc);
	if (!rc) {
		value = val;
		return true;
	} else
		return false;
}
//
// Send a keychain-related notification event about this database
//
void DbCommon::notify(NotificationEvent event, const DLDbIdentifier &ident)
{
	// form the data (encoded DLDbIdentifier)
    NameValueDictionary nvd;
    NameValueDictionary::MakeNameValueDictionaryFromDLDbIdentifier(ident, nvd);
    CssmData data;
    nvd.Export(data);

	// inject notification into Security event system
    Listener::notify(kNotificationDomainDatabase, event, data);
	
	// clean up
    free (data.data());
}
/* decode TBSCert and its extensions */
void DecodedCert::decodeTbs(
	const CssmData	&encodedTbs)
{
	assert(mState == IS_Empty);
	
	memset(&mCert, 0, sizeof(mCert));
	PRErrorCode prtn = mCoder.decode(encodedTbs.data(), encodedTbs.length(), 
		kSecAsn1TBSCertificateTemplate, &mCert.tbs);
	if(prtn) {
		CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
	}
	mDecodedExtensions.decodeFromNss(mCert.tbs.extensions);
	mState = IS_DecodedTBS;
}
Beispiel #16
0
//
// Send CDSA-layer notifications for this token.
// These events are usually received by CDSA plugins working with securityd.
//
void Token::notify(NotificationEvent event)
{
    NameValueDictionary nvd;
	CssmSubserviceUid ssuid(mGuid, NULL, h2n (mSubservice),
		h2n(CSSM_SERVICE_DL | CSSM_SERVICE_CSP));
	nvd.Insert(new NameValuePair(SSUID_KEY, CssmData::wrap(ssuid)));
    CssmData data;
    nvd.Export(data);

	// inject notification into Security event system
    Listener::notify(kNotificationDomainCDSA, event, data);
	
	// clean up
    free (data.data());
}
void SDContext::copyOutBuf(CssmData &out)
{
	if(out.length() < mOutBuf.length()) {
		CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
	}
	memmove(out.Data, mOutBuf.Data, mOutBuf.Length);
	out.Length = mOutBuf.Length;
	clearOutBuf();
}
/* new in 10.6 */
CFDataRef
SecCertificateCopyData(SecCertificateRef certificate)
{
	CFDataRef data = NULL;
    OSStatus __secapiresult = errSecSuccess;
	try {
		CssmData output = Certificate::required(certificate)->data();
		CFIndex length = (CFIndex)output.length();
		const UInt8 *bytes = (const UInt8 *)output.data();
		if (length && bytes) {
			data = CFDataCreate(NULL, bytes, length);
		}
	}
	catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
	catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
	catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
	catch (...) { __secapiresult=errSecInternalComponent; }
    return data;
}
/*
 * Set the field specified by fieldId in the specified Cert.
 * Note no index - individual field routines either append (for extensions)
 * or if field already set ::throwMe(for all others)
 */
void DecodedCert::setCertField(
	const CssmOid		&fieldId,		// which field
	const CssmData		&fieldValue)
{
	switch(mState) {
		case IS_Empty:			// first time thru
			mState = IS_Building;
			break;
		case IS_Building:		// subsequent passes
			break;
		case IS_DecodedAll:
		case IS_DecodedTBS:
			clErrorLog("DecodedCert::setCertField: can't build on a decoded cert!");
			CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
	}
	if((fieldValue.data() == NULL) || (fieldValue.length() == 0)) {
		CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
	}
	const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId);
	const CssmData &value = CssmData::overlay(fieldValue);
	fieldFuncs->setFcn(*this, value);
}
Beispiel #20
0
void KeychainDatabase::makeUnlocked(const CssmData &passphrase)
{
	if (isLocked()) {
		if (decode(passphrase))
			return;
		else
			CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED);
	} else if (!mValidData)	{	// need to decode to get our ACLs, passphrase available
		if (!decode())
			CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED);
	}

    if (common().isLoginKeychain()) {
        bool locked = false;
        service_context_t context = common().session().get_current_service_context();
        if ((service_client_kb_is_locked(&context, &locked, NULL) == 0) && locked) {
            unlock_keybag(common(), passphrase.data(), (int)passphrase.length());
        }
    }

	assert(!isLocked());
	assert(mValidData);
}
Beispiel #21
0
void unflattenKey(const CssmData &flatKey, CssmKey &rawKey)
{
	// unflatten the raw input key naively: key header then key data
	// We also convert it back to host byte order
	// A CSSM_KEY is a CSSM_KEYHEADER followed by a CSSM_DATA

	// Now copy: header, then key struct, then key data
	memcpy(&rawKey.KeyHeader, flatKey.Data, sizeof(CSSM_KEYHEADER));
	memcpy(&rawKey.KeyData, flatKey.Data + sizeof(CSSM_KEYHEADER), sizeof(CSSM_DATA));
	const uint32 keyDataLength = flatKey.length() - sizeof(CSSM_KEY);
	rawKey.KeyData.Data = Allocator::standard().malloc<uint8>(keyDataLength);
	rawKey.KeyData.Length = keyDataLength;
	memcpy(rawKey.KeyData.Data, flatKey.Data + sizeof(CSSM_KEY), keyDataLength);
	Security::n2hi(rawKey.KeyHeader);	// convert it to host byte order
}
static void setField_PublicKeyStruct (
	DecodedItem			&item,
	const CssmData		&fieldValue)
{
	DecodedCert &cert = dynamic_cast<DecodedCert &>(item);
	CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &dstKeyInfo =
		cert.mCert.tbs.subjectPublicKeyInfo;
	tbsSetCheck(dstKeyInfo.subjectPublicKey.Data, fieldValue,
		sizeof(CSSM_KEY), "PubKeyStruct");

	CSSM_KEY_PTR cssmKey = (CSSM_KEY_PTR)fieldValue.data();
	if((cssmKey->KeyData.Data == NULL) ||
	   (cssmKey->KeyData.Data == 0)) {
		CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
	}
	CL_CSSMKeyToSubjPubKeyInfoNSS(*cssmKey, dstKeyInfo, cert.coder());
}
Beispiel #23
0
void CryptKit::FEEBinaryKey::generateKeyBlob(
    Allocator			&allocator,
    CssmData			&blob,
    CSSM_KEYBLOB_FORMAT	&format,
    AppleCSPSession		&session,
    const CssmKey		*paramKey,	/* optional, unused here */
    CSSM_KEYATTR_FLAGS 	&attrFlags)	/* IN/OUT */
{
    unsigned char 	*keyBlob;
    unsigned 		len;
    feeReturn		frtn = FR_Internal;
    bool			freeTheKey = false;
    feePubKey		keyToEncode = mFeeKey;

    assert(mFeeKey != NULL);
    if((format == CSSM_KEYBLOB_RAW_FORMAT_DIGEST) &&
            (mKeyHeader.KeyClass == CSSM_KEYCLASS_PRIVATE_KEY)) {
        /* key digest calculation; special case for private keys: cook
         * up the associated public key and encode that */
        keyToEncode = feePubKeyAlloc();
        if(keyToEncode == NULL) {
            CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
        }
        frtn = feePubKeyInitPubKeyFromPriv(mFeeKey, keyToEncode);
        if(frtn) {
            feePubKeyFree(keyToEncode);
            throwCryptKit(frtn, "feePubKeyInitPubKeyFromPriv");
        }
        freeTheKey = true;
    }

    bool badFormat = false;
    int isPrivate = feePubKeyIsPrivate(keyToEncode);

    switch(mKeyHeader.AlgorithmId) {
    case CSSM_ALGID_FEE:
        if(isPrivate) {
            /* FEE private key */
            switch(format) {
            case CSSM_KEYBLOB_RAW_FORMAT_DIGEST:
                format = CSSM_KEYBLOB_RAW_FORMAT_NONE;
            /* and drop thru */
            case CSSM_KEYBLOB_RAW_FORMAT_NONE:
                frtn = feePubKeyCreateDERPrivBlob(keyToEncode, &keyBlob, &len);
                break;
            case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING:
                frtn = feePubKeyCreatePrivBlob(keyToEncode, &keyBlob, &len);
                break;
            default:
                badFormat = true;
                break;
            }
        }
        else {
            /* FEE Public key */
            switch(format) {
            case CSSM_KEYBLOB_RAW_FORMAT_DIGEST:
                format = CSSM_KEYBLOB_RAW_FORMAT_NONE;
            /* and drop thru */
            case CSSM_KEYBLOB_RAW_FORMAT_NONE:
                frtn = feePubKeyCreateDERPubBlob(keyToEncode, &keyBlob, &len);
                break;
            case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING:
                frtn = feePubKeyCreatePubBlob(keyToEncode, &keyBlob, &len);
                break;
            default:
                badFormat = true;
                break;
            }
        }
        /* end of base ALGID_FEE */
        break;

    case CSSM_ALGID_ECDSA:
        if(isPrivate) {
            /* ECDSA/ECDH private key */
            switch(format) {
            case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
                /* ECDSA private key: PKCS8 */
                frtn = feePubKeyCreatePKCS8Blob(keyToEncode, &keyBlob, &len);
                break;
            case CSSM_KEYBLOB_RAW_FORMAT_NONE:
                /* set to default format, drop thru */
                format = CSSM_KEYBLOB_RAW_FORMAT_OPENSSL;
            case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL:
                /* ECDSA private key, SEC1/OpenSSL format */
                frtn = feePubKeyCreateOpenSSLBlob(keyToEncode, &keyBlob, &len);
                break;
            case CSSM_KEYBLOB_RAW_FORMAT_DIGEST:
                format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING;
            /* and drop thru */
            case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING:
                /* raw private key bytes */
                frtn = feeCreateECDSAPrivBlob(keyToEncode, &keyBlob, &len);
                break;
            default:
                badFormat = true;
                break;
            }
        }
        else {
            /*
             * ECDSA public key.
             * Note there is no OpenSSL case here, that format is only generated for
             * private keys.
             */
            switch(format) {
            case CSSM_KEYBLOB_RAW_FORMAT_NONE:
                /* set to default format, drop thru */
                format = CSSM_KEYBLOB_RAW_FORMAT_X509;
            case CSSM_KEYBLOB_RAW_FORMAT_X509:
                /* ECDSA, public key, default: X509 */
                frtn = feePubKeyCreateX509Blob(keyToEncode, &keyBlob, &len);
                break;
            case CSSM_KEYBLOB_RAW_FORMAT_DIGEST:
                format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING;
            /* and drop thru */
            case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING:
                /* raw x|y string */
                frtn = feeCreateECDSAPubBlob(keyToEncode, &keyBlob, &len);
                break;
            default:
                badFormat = true;
                break;
            }
        }
        /* end of case CSSM_ALGID_ECDSA */
        break;
    default:
        /* not reached */
        break;
    }

    if(badFormat) {
        CssmError::throwMe(isPrivate ?
                           CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT :
                           CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT);
    }
    if(frtn) {
        throwCryptKit(frtn, "feePubKeyCreate*Blob");
    }
    setUpCssmData(blob, len, allocator);
    memmove(blob.data(), keyBlob, len);
    blob.length(len);
    ffree(keyBlob);
    if(freeTheKey) {
        /* free the temp pub key we created here */
        feePubKeyFree(keyToEncode);
    }
}
Beispiel #24
0
// this one is specified in, and called from, AppleKeyPairGenContext
void CryptKit::FEEKeyPairGenContext::generate(
    const Context 	&context,
    BinaryKey		&pubBinKey,
    BinaryKey		&privBinKey,
    uint32			&keyBits)
{
    /*
     * These casts throw exceptions if the keys are of the
     * wrong classes, which would be a major bogon, since we created
     * the keys in the above generate() function.
     */
    FEEBinaryKey &fPubBinKey =
        dynamic_cast<FEEBinaryKey &>(pubBinKey);
    FEEBinaryKey &fPrivBinKey =
        dynamic_cast<FEEBinaryKey &>(privBinKey);

    /*
     * Two parameters from context. Key size in bits is required;
     * seed is optional. If not present, we cook up random private data.
     */
    keyBits = context.getInt(CSSM_ATTRIBUTE_KEY_LENGTH,
                             CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH);
    CssmCryptoData *cseed = context.get<CssmCryptoData>(CSSM_ATTRIBUTE_SEED);
    CssmData *seed;
    bool haveSeed;
    CssmAutoData aSeed(session());		// malloc on demand
    if(cseed) {
        /* caller specified seed */
        haveSeed = true;
        seed = &cseed->param();
    }
    else {
        /* generate random seed */
        haveSeed = false;
        unsigned keyBytes = ((keyBits + 7) / 8) + 1;
        aSeed.malloc(keyBytes);
        session().getRandomBytes(keyBytes, aSeed);
        seed = &aSeed.get();
    }

    CSSM_ALGORITHMS algId = context.algorithm();

    /* Curve and prime types - optional */
    feePrimeType primeType = FPT_Default;
    uint32 uPrimeType = context.getInt(CSSM_ATTRIBUTE_FEE_PRIME_TYPE);
    switch(uPrimeType) {
    case CSSM_FEE_PRIME_TYPE_DEFAULT:
        break;
    case CSSM_FEE_PRIME_TYPE_MERSENNE:
        primeType = FPT_Mersenne;
        break;
    case CSSM_FEE_PRIME_TYPE_FEE:
        primeType = FPT_FEE;
        break;
    case CSSM_FEE_PRIME_TYPE_GENERAL:
        primeType = FPT_General;
        break;
    default:
        /* FIXME - maybe we should be more specific */
        CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS);
    }
    feeCurveType curveType = FCT_Default;
    switch(algId) {
    case CSSM_ALGID_ECDSA:
        /* no options */
        curveType = FCT_ANSI;
        break;
    default:
    {
        uint32 uCurveType = context.getInt(CSSM_ATTRIBUTE_FEE_CURVE_TYPE);
        switch(uCurveType) {
        case CSSM_FEE_CURVE_TYPE_DEFAULT:
            break;
        case CSSM_FEE_CURVE_TYPE_MONTGOMERY:
            curveType = FCT_Montgomery;
            break;
        case CSSM_FEE_CURVE_TYPE_WEIERSTRASS:
            curveType = FCT_Weierstrass;
            break;
        case CSSM_FEE_CURVE_TYPE_ANSI_X9_62:
            curveType = FCT_ANSI;
            break;
        default:
            /* FIXME - maybe we should be more specific */
            CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS);
        }
        break;
    }
    }
    feeReturn frtn = feePubKeyInitFromPrivDataKeyBits(
                         fPrivBinKey.feeKey(),
                         (unsigned char *)seed->data(),
                         (unsigned int)seed->length(),
                         keyBits,
                         primeType,
                         curveType,
                         /*
                          * our random seed: trust it
                          * caller's seed: hash it
                          */
                         haveSeed ? 1 : 0);
    if(frtn) {
        throwCryptKit(frtn, "feePubKeyInitFromPrivDataKeyBits");
    }
    frtn = feePubKeyInitPubKeyFromPriv(fPrivBinKey.feeKey(),
                                       fPubBinKey.feeKey());
    if(frtn) {
        throwCryptKit(frtn, "feePubKeyInitPubKeyFromPriv");
    }
}
void MacContext::update(const CssmData &data)
{
	CCHmacUpdate(&hmacCtx, data.data(), data.length());
}
Beispiel #26
0
void Session::resetKeyStorePassphrase(const CssmData &passphrase)
{
    service_context_t context = get_current_service_context();
    service_client_kb_reset(&context, passphrase.data(), (int)passphrase.length());
}
// update for input-only block/stream algorithms
void BSafe::BSafeContext::update(const CssmData &data)
{
	opStarted = true;
    check(inUpdate(bsAlgorithm, POINTER(data.data()), data.length(), bsSurrender));
}
Beispiel #28
0
void UnixDb::erase(const CssmData &key, int flags)
{
	Data dKey(key);
	secdebug("unixdb", "delete(%p,[:%ld],flags=0x%x)", mDb, key.length(), flags);
	checkError(mDb->del(mDb, &dKey, flags));
}
	END_SECAPI1(NULL);
}
*/

CSSM_RETURN
SecDigestGetData (CSSM_ALGORITHMS alg, CSSM_DATA* digest, const CSSM_DATA* data)
{
	BEGIN_SECAPI
	// sanity checking
	if (!digest || !digest->Data || !digest->Length || !data || !data->Data || !data->Length)
		return errSecParam;

	CSP csp(gGuidAppleCSP);
	Digest context(csp, alg);
	CssmData input(data->Data, data->Length);
	CssmData output(digest->Data, digest->Length);

	context.digest(input, output);
	digest->Length = output.length();

	return CSSM_OK;
	END_SECAPI1(1);
}

/* determine whether a cert is self-signed */
OSStatus SecCertificateIsSelfSigned(
	SecCertificateRef certificate,
	Boolean *isSelfSigned)		/* RETURNED */
{
    BEGIN_SECAPI