2 * ascContext.cpp - glue between BlockCrytpor and ComCryption (a.k.a. Apple
4 * Written by Doug Mitchell 4/4/2001
9 #include "ascContext.h"
10 #include "ascFactory.h"
11 #include <Security/debugging.h>
12 #include <Security/logging.h>
13 #include <Security/cssmapple.h>
15 #define abprintf(args...) secdebug("ascBuf", ## args) /* buffer sizes */
16 #define aioprintf(args...) secdebug("ascIo", ## args) /* all I/O */
18 static CssmAllocator
*ascAllocator
;
21 * Comcryption-style memory allocator callbacks
23 static void *ccMalloc(unsigned size
)
25 return ascAllocator
->malloc(size
);
27 static void ccFree(void *data
)
29 ascAllocator
->free(data
);
32 /* Given a ComCryption error, throw appropriate CssmError */
33 static void throwComcrypt(
35 const char *op
) /* optional */
37 CSSM_RETURN cerr
= CSSM_OK
;
38 const char *errStr
= "Bad Error String";
42 errStr
= "CCR_SUCCESS";
44 case CCR_OUTBUFFER_TOO_SMALL
:
45 errStr
= "CCR_OUTBUFFER_TOO_SMALL";
46 cerr
= CSSMERR_CSP_OUTPUT_LENGTH_ERROR
;
48 case CCR_MEMORY_ERROR
:
49 errStr
= "CCR_MEMORY_ERROR";
50 cerr
= CSSMERR_CSP_MEMORY_ERROR
;
52 case CCR_WRONG_VERSION
:
53 errStr
= "CCR_WRONG_VERSION";
54 cerr
= CSSMERR_CSP_INVALID_DATA
;
56 case CCR_BAD_CIPHERTEXT
:
57 errStr
= "CCR_BAD_CIPHERTEXT";
58 cerr
= CSSMERR_CSP_INVALID_DATA
;
62 errStr
= "CCR_INTERNAL";
63 cerr
= CSSMERR_CSP_INTERNAL_ERROR
;
67 Security::Syslog::error("Apple CSP %s: %s", op
, errStr
);
70 CssmError::throwMe(cerr
);
78 AscAlgFactory::AscAlgFactory(
79 CssmAllocator
*normAlloc
,
80 CssmAllocator
*privAlloc
)
82 /* once-per-address-space init */
83 ascAllocator
= privAlloc
;
84 comMallocRegister(ccMalloc
, ccFree
);
87 bool AscAlgFactory::setup(
88 AppleCSPSession
&session
,
89 CSPFullPluginSession::CSPContext
* &cspCtx
,
90 const Context
&context
)
92 if(context
.algorithm() != CSSM_ALGID_ASC
) {
96 /* reusing one of ours; OK */
99 switch(context
.type()) {
100 case CSSM_ALGCLASS_KEYGEN
:
101 cspCtx
= new AppleSymmKeyGenerator(session
,
103 COMCRYPT_MAX_KEYLENGTH
* 8,
104 true); // must be byte size
106 case CSSM_ALGCLASS_SYMMETRIC
:
107 cspCtx
= new ASCContext(session
);
116 ASCContext::~ASCContext()
119 comcryptObjFree(mCcObj
);
124 * Standard CSPContext init, called from CSPFullPluginSession::init().
125 * Reusable, e.g., query followed by en/decrypt.
127 void ASCContext::init(
128 const Context
&context
,
132 UInt8
*keyData
= NULL
;
135 /* obtain key from context */
136 symmetricKeyBits(context
, CSSM_ALGID_ASC
,
137 encrypting
? CSSM_KEYUSE_ENCRYPT
: CSSM_KEYUSE_DECRYPT
,
139 if((keyLen
< 1) || (keyLen
> COMCRYPT_MAX_KEYLENGTH
)) {
140 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY
);
142 mDecryptBufValid
= false;
144 /* optional optimization attribute */
145 comcryptOptimize optimize
= CCO_DEFAULT
;
146 uint32 opt
= context
.getInt(CSSM_ATTRIBUTE_ASC_OPTIMIZATION
);
148 case CSSM_ASC_OPTIMIZE_DEFAULT
:
149 optimize
= CCO_DEFAULT
;
151 case CSSM_ASC_OPTIMIZE_SIZE
:
154 case CSSM_ASC_OPTIMIZE_SECURITY
:
155 optimize
= CCO_SECURITY
;
157 case CSSM_ASC_OPTIMIZE_TIME
:
160 case CSSM_ASC_OPTIMIZE_TIME_SIZE
:
161 optimize
= CCO_TIME_SIZE
;
163 case CSSM_ASC_OPTIMIZE_ASCII
:
164 optimize
= CCO_ASCII
;
167 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS
);
170 /* All other context attributes ignored */
171 /* init the low-level state */
173 /* note we allow for context reuse */
174 mCcObj
= comcryptAlloc();
176 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR
);
180 crtn
= comcryptInit(mCcObj
, keyData
, keyLen
, optimize
);
182 throwComcrypt(crtn
, "comcryptInit");
187 * All of these functions are called by CSPFullPluginSession.
189 void ASCContext::update(
191 size_t &inSize
, // in/out
193 size_t &outSize
) // in/out
197 unsigned char *inText
= (unsigned char *)inp
;
198 unsigned char *outText
= (unsigned char *)outp
;
202 crtn
= comcryptData(mCcObj
,
207 CCE_MORE_TO_COME
); // not used on encrypt
209 throwComcrypt(crtn
, "comcryptData");
214 * Deal with 1-byte buffer hack. First decrypt the existing buffer...
217 CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR
);
220 unsigned partialOutLen
= 0;
221 if(mDecryptBufValid
) {
222 thisOutLen
= outSize
;
223 crtn
= deComcryptData(mCcObj
,
229 mDecryptBufValid
= false;
231 throwComcrypt(crtn
, "deComcryptData (1)");
233 partialOutLen
= thisOutLen
;
234 outText
+= thisOutLen
;
238 * Now decrypt remaining, less one byte (which is stored in the
241 thisOutLen
= outSize
- partialOutLen
;
242 crtn
= deComcryptData(mCcObj
,
249 throwComcrypt(crtn
, "deComcryptData (2)");
251 outLen
= partialOutLen
+ thisOutLen
;
252 mDecryptBuf
= inText
[inSize
- 1];
253 mDecryptBufValid
= true;
256 aioprintf("=== ASC::update encrypt %d inSize %ld outSize %ld",
257 encoding() ? 1 : 0, inSize
, outSize
);
260 void ASCContext::final(
267 /* decrypt buffer hack */
268 if(!mDecryptBufValid
) {
269 CssmError::throwMe(CSSMERR_CSP_INPUT_LENGTH_ERROR
);
272 unsigned outLen
= out
.Length
;
273 crtn
= deComcryptData(mCcObj
,
276 (unsigned char *)out
.Data
,
279 mDecryptBufValid
= false;
281 throwComcrypt(crtn
, "deComcryptData (3)");
285 aioprintf("=== ASC::final encrypt %d outSize %ld",
286 encoding() ? 1 : 0, out
.Length
);
289 size_t ASCContext::inputSize(
290 size_t outSize
) // input for given output size
292 size_t rtn
= comcryptMaxInBufSize(mCcObj
,
294 encoding() ? CCOP_COMCRYPT
: CCOP_DECOMCRYPT
);
295 abprintf("--- ASCContext::inputSize inSize %ld outSize %ld",
301 * ComCryption's buffer size calculation really does not lend itself to the
302 * requirements here. For example, there is no guarantee that
303 * inputSize(outputSize(x)) == x. We're just going to fudge it and make
304 * apps (or CSPFullPluginSession) alloc plenty more than they need.
306 #define ASC_OUTSIZE_FUDGE 1
307 #define ASC_OUTSIZE_FUDGE_FACTOR 1.2
309 size_t ASCContext::outputSize(
311 size_t inSize
) // output for given input size
313 unsigned effectiveInSize
= inSize
;
316 rtn
= comcryptMaxOutBufSize(mCcObj
,
320 #if ASC_OUTSIZE_FUDGE
321 float newOutSize
= rtn
;
322 newOutSize
*= ASC_OUTSIZE_FUDGE_FACTOR
;
323 rtn
= static_cast<size_t>(newOutSize
);
324 #endif /* ASC_OUTSIZE_FUDGE */
328 if(mDecryptBufValid
) {
332 else if(inSize
&& !mDecryptBufValid
) {
333 /* not final and nothing buffered yet - lop off one */
336 rtn
= comcryptMaxOutBufSize(mCcObj
,
341 abprintf("--- ASCContext::outputSize inSize %ld outSize %ld final %d ",
346 void ASCContext::minimumProgress(
348 size_t &out
) // minimum progress chunks
352 out
= comcryptMaxOutBufSize(mCcObj
,
358 if(mDecryptBufValid
) {
359 /* use "everything" */
365 out
= comcryptMaxOutBufSize(mCcObj
,
370 abprintf("--- ASCContext::minProgres in %ld out %ld", in
, out
);
373 #endif /* ASC_CSP_ENABLE */