1/*
2 * Copyright (c) 2000-2001,2011,2013-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 * BlockCryptor.h - common context for block-oriented encryption algorithms
21 *
22 */
23
24#ifndef	_BLOCK_CRYPTOR_H_
25#define _BLOCK_CRYPTOR_H_
26
27#include "AppleCSPContext.h"
28
29/*
30 * Base class for AppleCSPContexts associated with BlockCryptObjects.
31 * The main purpose of this class is to abstract out the very common work
32 * of buffering incoming data (per CSSM-style update, ..., final) and
33 * doing single-block ops on the underlying encrypt/decrypt algorithm
34 * objects. Standard PKSC5 padding is handled here. All other chaining,
35 * padding, IV, et al, logic is handled by subclasses.
36 */
37class BlockCryptor : public AppleCSPContext
38{
39public:
40	BlockCryptor(
41		AppleCSPSession &session) :
42			AppleCSPContext(session),
43			mOpStarted(false),
44			mCbcCapable(false),
45			mMultiBlockCapable(false),
46			mInBuf(NULL),
47			mChainBuf(NULL) { }
48	virtual ~BlockCryptor();
49
50	/*
51	 * Note standard init(const Context &context, bool encoding) is totally
52	 * subclass-specific.
53	 *
54	 * These are implemented here using the subclass's {en,de}cryptBlock functions.
55	 * Note PKCS5 padding is implemented here if mPkcs5Padding is true. PKCS5
56	 * padding can only be accomplished if the result of decrypting
57	 * cipherBlockSize() bytes of ciphertext yields exactly plainBlockSize()
58	 * bytes of plaintext. (Sound odd? FEED does not meet that restriction...)
59	 */
60	void update(
61		void 			*inp,
62		size_t 			&inSize, 			// in/out
63		void 			*outp,
64		size_t 			&outSize);			// in/out
65
66	void final(
67		CssmData 		&out);
68
69	/*
70	 * Our implementation of these three query functions are only valid
71	 * for algorithms for which encrypting one block of plaintext always
72	 * yields exactly one block of ciphertext, and vice versa for decrypt.
73	 * The block sizes for plaintext and ciphertext do NOT have to be the same.
74	 * Subclasses (e.g. FEED) which do not meet this criterion will have to override.
75	 */
76 	virtual size_t inputSize(
77		size_t 			outSize);			// input for given output size
78	virtual size_t outputSize(
79		bool 			final = false,
80		size_t 			inSize = 0); 		// output for given input size
81	virtual void minimumProgress(
82		size_t 			&in,
83		size_t 			&out); 				// minimum progress chunks
84
85protected:
86	typedef enum {
87		BCM_ECB,			// no chaining
88		BCM_CBC				// requires inBlockSize == outBlockSize
89	} BC_Mode;
90
91	/* accessors (see comments below re: the member variables) */
92	bool	pkcs5Padding()		{ return mPkcsPadding; }
93	bool	needFinalData()		{ return mNeedFinalData; }
94	void	*inBuf()			{ return mInBuf; }
95	size_t	inBufSize()			{ return mInBufSize; }
96	void	*chainBuf()			{ return mChainBuf; }
97	size_t	inBlockSize()		{ return mInBlockSize; }
98	size_t	outBlockSize()		{ return mOutBlockSize; }
99	BC_Mode	mode()				{ return mMode; }
100	bool	opStarted()			{ return mOpStarted; }
101	bool	cbcCapable()		{ return mCbcCapable; }
102	void	cbcCapable(bool c)	{ mCbcCapable = c; }
103	bool	multiBlockCapable()	{ return mMultiBlockCapable; }
104	void	multiBlockCapable(bool c)	{ mMultiBlockCapable = c; }
105
106	/*
107	 * Reusable setup functions called from subclass's init.
108	 * This is the general purpose one....
109	 */
110	void	setup(
111		size_t			blockSizeIn,	// block size of input in bytes
112		size_t			blockSizeOut,	// block size of output in bytes
113		bool			pkcsPad,		// this class performs PKCS{5,7} padding
114		bool			needsFinal,		// needs final update with valid data
115		BC_Mode			mode,			// ECB, CBC
116		const CssmData	*iv);			// init vector, required for CBC
117										//�  must be at least blockSizeIn bytes
118
119	/*
120	 * This one is used by simple, well-behaved algorithms which don't do their own
121	 * padding and which rely on us to do everything but one-block-at-a-time
122	 * encrypt and decrypt.
123	 */
124	void setup(
125		size_t			blockSize,		// block size of input and output
126		const Context 	&context);
127
128	/***
129	 *** Routines to be implemented by subclass.
130	 ***/
131
132	/*
133	virtual void init(const Context &context, bool encoding = true);
134	*/
135
136	/*
137	 * encrypt/decrypt exactly one block. Output buffers mallocd by caller.
138	 * On encrypt, it may be acceptable for plainTextLen to be less than
139	 * one plainBlockSize() if:
140	 *   -- final is true, and
141	 *   -- the subclass permits this. That is generally only true
142	 *      when the subclass implements some padding other than our
143	 *      standard PKCS5.
144	 *
145	 * The subclass throws CSSMERR_CSP_INPUT_LENGTH_ERROR if the above
146	 * conditions are not met.
147	 */
148	virtual void encryptBlock(
149		const void		*plainText,			// length implied (one block)
150		size_t			plainTextLen,
151		void			*cipherText,
152		size_t			&cipherTextLen,		// in/out, subclass throws on overflow
153		bool			final) = 0;
154
155	/*
156	 * Decrypt one block. Incoming cipherText length is ALWAYS cipherBlockSize().
157	 */
158	virtual void decryptBlock(
159		const void		*cipherText,		// length implied (one cipher block)
160		size_t			cipherTextLen,
161		void			*plainText,
162		size_t			&plainTextLen,		// in/out, subclass throws on overflow
163		bool			final) = 0;
164
165private:
166	bool				mOpStarted;			// for optional use by subclasses when
167											//   resuing context after encrypt/decrypt
168											//   ops occur
169	bool				mCbcCapable;		// when true, algorithm can do its own CBC
170	bool				mMultiBlockCapable;	// when true, algorithm can do multi-block ops
171
172	/* these are all init'd via setup(), called from subclass-specific init */
173	bool				mPkcsPadding;		// PKCS{5,7} padding enabled
174	bool				mNeedFinalData;		// subclass needs an update(final) with
175											//   valid data; if true we always keep
176											//   some data in mInBuf after an update.
177											//   Mutually exclusive with mPkcsPadding.
178	uint8 				*mInBuf;			// for buffering input
179	size_t				mInBufSize;			// valid bytes in mInBuf
180	uint8				*mChainBuf;			// for CBC, decrypting only
181	size_t				mInBlockSize;		// block size of input in bytes; also
182											//    mallocd size of mInBuf
183	size_t				mOutBlockSize;		// block size of output in bytes
184	BC_Mode				mMode;				// ECB, CBC
185
186};
187
188#endif	/* _BLOCK_CRYPTOR_H_ */
189