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