1/*
2 * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19/*
20 * bfContext.cpp - glue between BlockCrytpor and ssleay Blowfish
21 *				 implementation
22 */
23
24#include "bfContext.h"
25
26BlowfishContext::~BlowfishContext()
27{
28	deleteKey();
29}
30
31void BlowfishContext::deleteKey()
32{
33	memset(&mBfKey, 0, sizeof(mBfKey));
34	mInitFlag = false;
35}
36
37/*
38 * Standard CSPContext init, called from CSPFullPluginSession::init().
39 * Reusable, e.g., query followed by en/decrypt.
40 */
41void BlowfishContext::init(
42	const Context &context,
43	bool encrypting)
44{
45	if(mInitFlag && !opStarted()) {
46		return;
47	}
48
49	CSSM_SIZE	keyLen;
50	uint8 		*keyData = NULL;
51	bool		sameKeySize = false;
52
53	/* obtain key from context */
54	symmetricKeyBits(context, session(), CSSM_ALGID_BLOWFISH,
55		encrypting ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT,
56		keyData, keyLen);
57	if((keyLen < BF_MIN_KEY_SIZE_BYTES) || (keyLen > BF_MAX_KEY_SIZE_BYTES)) {
58		CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY);
59	}
60
61	/*
62	 * Delete existing key if key size changed
63	 */
64	if(mRawKeySize == keyLen) {
65		sameKeySize = true;
66	}
67	else {
68		deleteKey();
69	}
70
71	/* init key only if key size or key bits have changed */
72	if(!sameKeySize || memcmp(mRawKey, keyData, mRawKeySize)) {
73		BF_set_key(&mBfKey, (int)keyLen, keyData);
74
75		/* save this raw key data */
76		memmove(mRawKey, keyData, keyLen);
77		mRawKeySize = (unsigned int)keyLen;
78	}
79
80	/* Finally, have BlockCryptor do its setup */
81	setup(BF_BLOCK, context);
82	mInitFlag = true;
83}
84
85/*
86 * Functions called by BlockCryptor
87 */
88void BlowfishContext::encryptBlock(
89	const void		*plainText,			// length implied (one block)
90	size_t			plainTextLen,
91	void			*cipherText,
92	size_t			&cipherTextLen,		// in/out, throws on overflow
93	bool			final)				// ignored
94{
95	if(plainTextLen != BF_BLOCK) {
96		CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR);
97	}
98	if(cipherTextLen < BF_BLOCK) {
99		CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
100	}
101	BF_ecb_encrypt((const unsigned char *)plainText, (unsigned char *)cipherText,
102		&mBfKey, BF_ENCRYPT);
103	cipherTextLen = BF_BLOCK;
104}
105
106void BlowfishContext::decryptBlock(
107	const void		*cipherText,		// length implied (one block)
108	size_t			cipherTextLen,
109	void			*plainText,
110	size_t			&plainTextLen,		// in/out, throws on overflow
111	bool			final)				// ignored
112{
113	if(plainTextLen < BF_BLOCK) {
114		CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
115	}
116	BF_ecb_encrypt((const unsigned char *)cipherText, (unsigned char *)plainText,
117		&mBfKey, BF_DECRYPT);
118	plainTextLen = BF_BLOCK;
119}
120