コード例 #1
0
int LoadSaveThread::exifOrientation(const QString& filePath, const DMetadata& metadata,
                                    bool isRaw, bool fromRawEmbeddedPreview)
{
    int dbOrientation = KExiv2::ORIENTATION_UNSPECIFIED;
    if (infoProvider())
    {
        dbOrientation = infoProvider()->orientationHint(filePath);
    }

    int exifOrientation = metadata.getImageOrientation();

    // Raw files are already rotated properly by dcraw. Only perform auto-rotation with JPEG/PNG/TIFF file.
    // We don't have a feedback from dcraw about auto-rotated RAW file during decoding.

    if (isRaw && !fromRawEmbeddedPreview)
    {
        // Did the user apply any additional rotation over the metadata flag?
        if (dbOrientation == KExiv2::ORIENTATION_UNSPECIFIED || dbOrientation == exifOrientation)
        {
            return KExiv2::ORIENTATION_NORMAL;
        }
        // Assume A is the orientation as from metadata, B is an additional operation applied by the user,
        // C is the current orientation in the database.
        // A*B = C and B = A_inv * C
        QMatrix A = KExiv2Iface::RotationMatrix::toMatrix((KExiv2::ImageOrientation)exifOrientation);
        QMatrix C = KExiv2Iface::RotationMatrix::toMatrix((KExiv2::ImageOrientation)dbOrientation);
        QMatrix A_inv = A.inverted();
        QMatrix B = A_inv * C;
        RotationMatrix m(B.m11(), B.m12(), B.m21(), B.m22());
        return m.exifOrientation();
    }

    if (dbOrientation != KExiv2::ORIENTATION_UNSPECIFIED)
    {
        return dbOrientation;
    }
    return exifOrientation;
}
コード例 #2
0
/*
 * Unwrap key function. Used for:
 *
 * -- Given key of BlobType CSSM_KEYBLOB_WRAPPED, decode and decrypt
 *    it, yielding a key in either raw or reference format. Unwrapping
 *    key may be either raw or reference. The context must match
 *    the unwrapping key (ALGCLASS_SYMMETRIC  or ALGCLASS_ASYMMETRIC).
 *
 *	  Private keys are assumed to be PKCS8 encoded; session keys  
 *    are assumed to be PKCS7 encoded. 
 *
 * -- Convert a Raw key to a reference key (with no decrypting).
 *    This is called a NULL unwrap; no unwrapping key need be present in
 *    the context, but the context must be of class 
 *    ALGCLASS_SYMMETRIC and algorithm ALGID_NONE.
 */ 
void AppleCSPSession::UnwrapKey(
		CSSM_CC_HANDLE CCHandle,
		const Context &Context,
		const CssmKey *PublicKey,
		const CssmKey &WrappedKey,
		uint32 KeyUsage,
		uint32 KeyAttr,
		const CssmData *KeyLabel,
		const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry,
		CssmKey &UnwrappedKey,
		CssmData &DescriptiveData,
		CSSM_PRIVILEGE Privilege)
{
	bool 					isNullUnwrap = false;
	CssmKey					*unwrappingKey = NULL;
	cspKeyType				keyType;				// CKT_Public, etc. 
	CSSM_KEYBLOB_FORMAT		wrapFormat = WrappedKey.blobFormat();
	
	/* obtain unwrapping key if present */
	unwrappingKey = Context.get<CssmKey>(CSSM_ATTRIBUTE_KEY);
	if(unwrappingKey == NULL) {
		if((Context.algorithm() == CSSM_ALGID_NONE) &&
		   (Context.type() == CSSM_ALGCLASS_SYMMETRIC)) {
				// NULL unwrap, OK
				isNullUnwrap = true;
		}
		else {
			errorLog0("UnwrapKey: missing wrapping key\n");
			CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_KEY);
		}
	}

	/* 
	 * validate unwrappingKey 
	 */
	if(!isNullUnwrap) {
		/* make sure unwrapping key type matches context */
		CSSM_CONTEXT_TYPE unwrapType;
		switch(unwrappingKey->KeyHeader.KeyClass) {
			case CSSM_KEYCLASS_PUBLIC_KEY:
			case CSSM_KEYCLASS_PRIVATE_KEY:
				unwrapType = CSSM_ALGCLASS_ASYMMETRIC;
				break;
			case CSSM_KEYCLASS_SESSION_KEY:
				unwrapType = CSSM_ALGCLASS_SYMMETRIC;
				break;
			default:
				errorLog0("UnwrapKey: bad class of wrappingKey\n");
				CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY);
		}
		if(unwrapType != Context.type()) {
			errorLog0("UnwrapKey: mismatch unwrappingKey/contextType\n");
			CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT);
		}
		if(Context.algorithm() == CSSM_ALGID_NONE) {
			errorLog0("UnwrapKey: null wrap alg, non-null key\n");
			CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
		}
		cspValidateIntendedKeyUsage(&unwrappingKey->KeyHeader, CSSM_KEYUSE_UNWRAP);
		cspVerifyKeyTimes(unwrappingKey->KeyHeader);
	}

	/* validate WrappedKey */
	switch(WrappedKey.keyClass()) {
		case CSSM_KEYCLASS_PUBLIC_KEY:
			#if 	!ALLOW_PUB_KEY_WRAP
			if(!isNullUnwrap) {
				errorLog0("UnwrapKey: unwrap of public key illegal\n");
				CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
			}
			#endif	/* ALLOW_PUB_KEY_WRAP */
			keyType = CKT_Public;
			break;
		case CSSM_KEYCLASS_PRIVATE_KEY:
			keyType = CKT_Private;
			break;
		case CSSM_KEYCLASS_SESSION_KEY:
			keyType = CKT_Session;
			break;
		default:
			CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
	}
	if(isNullUnwrap) {
		if(WrappedKey.blobType() != CSSM_KEYBLOB_RAW) {
			errorLog0("UnwrapKey: expected raw blobType\n");
			CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT);
		}
	}
	else {
		if(WrappedKey.blobType() != CSSM_KEYBLOB_WRAPPED) {
			errorLog0("UnwrapKey: expected wrapped blobType\n");
			CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT);
		}
	}

	/* validate requested storage and usage */
	cspKeyStorage keyStorage = cspParseKeyAttr(keyType, KeyAttr);
	switch(keyStorage) {
		case CKS_Ref:
		case CKS_Data:
			break;		// OK
		default:
			CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK);
	}
	cspValidateKeyUsageBits(keyType,  KeyUsage);

	/* prepare outgoing header */
	CssmKey::Header &unwrappedHdr = UnwrappedKey.header();
	const CssmKey::Header &wrappedHdr   = WrappedKey.header();
	setKeyHeader(unwrappedHdr,
		plugin.myGuid(),
		wrappedHdr.algorithm(),		// same as incoming 
		wrappedHdr.keyClass(),		// same as incoming
		KeyAttr & ~KEY_ATTR_RETURN_MASK,
		KeyUsage);
	unwrappedHdr.LogicalKeySizeInBits = wrappedHdr.LogicalKeySizeInBits;
	unwrappedHdr.StartDate = wrappedHdr.StartDate;
	unwrappedHdr.EndDate = wrappedHdr.EndDate;
	UnwrappedKey.KeyData.Data = NULL;	// ignore possible incoming KeyData
	UnwrappedKey.KeyData.Length = 0;
	
	/* validate wrappedKey format */
	if(!isNullUnwrap) {
		switch(wrapFormat) {
			case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7:
				if(WrappedKey.keyClass() != CSSM_KEYCLASS_SESSION_KEY) {
					/* this unwrapping style only for symmetric keys */
					CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
				}
				break;
			case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8:
			case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSL:
				if(WrappedKey.keyClass() != CSSM_KEYCLASS_PRIVATE_KEY) {
					/* these unwrapping styles only for private keys */
					CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
				}
				break;
			case CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM:
				UnwrapKeyCms(CCHandle,
						Context,
						WrappedKey,
						CredAndAclEntry,
						UnwrappedKey,
						DescriptiveData,
						Privilege,
						keyStorage);
				return;
			case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1:
				/* RSA private key, unwrap to ref key only */
				if(WrappedKey.keyClass() != CSSM_KEYCLASS_PRIVATE_KEY) {
					CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
				}
				if(WrappedKey.algorithm() != CSSM_ALGID_RSA) {
					CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
				}
				if(keyStorage != CKS_Ref) {
					errorLog0("UNwrapKey: OPENSSH1 only wraps to reference key\n");
					CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT);
				}
				UnwrapKeyOpenSSH1(CCHandle,
						Context,
						WrappedKey,
						CredAndAclEntry,
						UnwrappedKey,
						DescriptiveData,
						Privilege,
						keyStorage);
				return;
			default:
				CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_WRAPPED_KEY_FORMAT);
		}
	}

	/* Get key blob, decoding and decrypting if necessary */
	CssmData decodedBlob;
	CssmData remData;
	try {
		if(isNullUnwrap) {
			/* simple copy of raw blob */
			copyData(WrappedKey.KeyData, 
				UnwrappedKey.KeyData, 
				normAllocator);
			unwrappedHdr.BlobType = CSSM_KEYBLOB_RAW;
			unwrappedHdr.Format   = wrapFormat; 
		}
		else {
			decodedBlob = CssmData::overlay(WrappedKey.KeyData);
			CSSM_SIZE bytesDecrypted;		
			CssmData *unwrapData = 
				CssmData::overlay(&UnwrappedKey.KeyData);
				
			DecryptData(CCHandle,
				Context,
				&decodedBlob,		// CipherBufs[],
				1,					// CipherBufCount,
				unwrapData,			// ClearBufs[]
				1,					// ClearBufCount
				bytesDecrypted,
				remData,
				Privilege);
	
			// I'm not 100% sure about this....
			assert(remData.Length == 0);
			UnwrappedKey.KeyData.Length = bytesDecrypted;
			unwrappedHdr.BlobType = CSSM_KEYBLOB_RAW;
			
			/* 
			 * Figure out various header fields from resulting blob
			 */
			switch(wrapFormat) {
				case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7:
					unwrappedHdr.Format = 
						CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING;
					if(unwrappedHdr.LogicalKeySizeInBits == 0) {
						unwrappedHdr.LogicalKeySizeInBits =
							(unsigned)(bytesDecrypted * 8);
					}
					/* app has to infer/know algorithm */
					break;
				case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8:
					pkcs8InferKeyHeader(UnwrappedKey);
					break;
				case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSL:
					/* 
					 * App told us key algorithm (in WrappedKey).
					 * Infer format and key size. 
					 */
					opensslInferKeyHeader(UnwrappedKey);
					break;
			}
		}
	}
	catch (...) {
		errorLog0("UnwrapKey: DecryptData() threw exception\n");
		freeCssmData(remData, normAllocator);
		throw;
	}
	freeCssmData(remData, normAllocator);

	/* 
	 * One more thing: cook up a BinaryKey if caller wants a 
	 * reference key.
	 */
	if(keyStorage == CKS_Ref) {
		/*
		 * We have a key in raw format; convert to BinaryKey.
		 */
		BinaryKey *binKey = NULL;
		CSPKeyInfoProvider *provider = infoProvider(UnwrappedKey);
		/* optional parameter-bearing key */
		CssmKey *paramKey = Context.get<CssmKey>(CSSM_ATTRIBUTE_PARAM_KEY);
		provider->CssmKeyToBinary(paramKey, UnwrappedKey.KeyHeader.KeyAttr, &binKey);
		addRefKey(*binKey, UnwrappedKey);
		delete provider;
	}
}