2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
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
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.
20 * FEEAsymmetricContext.cpp - CSPContexts for FEE asymmetric encryption
22 * Created March 8 2001 by dmitch.
25 #ifdef CRYPTKIT_CSP_ENABLE
27 #include "FEEAsymmetricContext.h"
28 #include "FEECSPUtils.h"
29 #include <Security/utilities.h>
31 /* validate context for FEED and FEEDExp - no unexpected attributes allowed */
32 static void validateFeedContext(
33 const Context
&context
)
35 /* Note we cannot distinguish between zero and "not there" */
36 uint32 blockSize
= context
.getInt(CSSM_ATTRIBUTE_BLOCK_SIZE
);
38 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_BLOCK_SIZE
);
40 CSSM_ENCRYPT_MODE cssmMode
= context
.getInt(CSSM_ATTRIBUTE_MODE
);
42 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_MODE
);
45 /* we allow this for CMS wrapping */
46 CssmData
*iv
= context
.get
<CssmData
>(CSSM_ATTRIBUTE_INIT_VECTOR
);
48 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_INIT_VECTOR
);
51 CSSM_PADDING padding
= context
.getInt(CSSM_ATTRIBUTE_PADDING
);
53 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING
);
58 *** FEED - 1:1 FEED - encrypt n bytes of plaintext, get (roughly) n bytes
59 *** of ciphertext. Ciphertext is smaller than with FEED, but this is slower.
61 CryptKit::FEEDContext::~FEEDContext()
64 feeFEEDFree(mFeeFeed
);
67 if(mPrivKey
&& mAllocdPrivKey
) {
68 feePubKeyFree(mPrivKey
);
70 if(mPubKey
&& mAllocdPubKey
) {
71 feePubKeyFree(mPubKey
);
78 // called by CSPFullPluginSession; reusable
79 void CryptKit::FEEDContext::init(
80 const Context
&context
,
83 if(mInitFlag
&& !opStarted()) {
84 /* reusing - e.g. query followed by encrypt */
89 * Fetch FEE keys from context. This is an unusual algorithm - it requires
90 * two keys, one public and one private. The public key MUST be stored in
91 * the context with attribute type CSSM_ATTRIBUTE_PUBLIC_KEY, and the private
92 * key with CSSM_ATTRIBUTE_KEY.
94 * For now, we require CSSM_KEYUSE_ANY for FEE keys used for this algorithm.
95 * Otherwise we'd have to allow both KEYUSE_ENCRYPT and KEYUSE_DECRYPT for
96 * both keys, and that would require some algorithm-specific hack in
97 * cspValidateKeyUsageBits() which I really don't want to do.
99 if(mPrivKey
== NULL
) {
100 assert(!opStarted());
101 mPrivKey
= contextToFeeKey(context
,
104 CSSM_KEYCLASS_PRIVATE_KEY
,
111 if(mPubKey
== NULL
) {
112 assert(!opStarted());
113 mPubKey
= contextToFeeKey(context
,
115 CSSM_ATTRIBUTE_PUBLIC_KEY
,
116 CSSM_KEYCLASS_PUBLIC_KEY
,
124 /* validate context - no other attributes allowed */
125 validateFeedContext(context
);
127 if(mFeeFeed
!= NULL
) {
130 feeFEEDFree(mFeeFeed
);
134 /* OK, looks good. Cook up a feeFEED object. */
135 mFeeFeed
= feeFEEDNewWithPubKey(mPrivKey
,
140 if(mFeeFeed
== NULL
) {
141 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY
);
144 /* finally, have BlockCryptor set up its stuff. */
145 unsigned plainBlockSize
= feeFEEDPlainBlockSize(mFeeFeed
);
146 unsigned cipherBlockSize
= feeFEEDCipherBlockSize(mFeeFeed
);
147 setup(encoding
? plainBlockSize
: cipherBlockSize
, // blockSizeIn
148 encoding
? cipherBlockSize
: plainBlockSize
, // blockSizeOut
156 // called by BlockCryptor
157 void CryptKit::FEEDContext::encryptBlock(
158 const void *plainText
, // length implied (one block)
161 size_t &cipherTextLen
, // in/out, throws on overflow
167 assert(mFeeFeed
!= NULL
);
168 frtn
= feeFEEDEncryptBlock(mFeeFeed
,
169 (unsigned char *)plainText
,
171 (unsigned char *)cipherText
,
175 throwCryptKit(frtn
, "feeFEEDEncryptBlock");
177 if(actMoved
> cipherTextLen
) {
178 /* Overflow already occurred! */
179 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR
);
181 cipherTextLen
= actMoved
;
184 void CryptKit::FEEDContext::decryptBlock(
185 const void *cipherText
, // length implied (one cipher block)
187 size_t &plainTextLen
, // in/out, throws on overflow
193 assert(mFeeFeed
!= NULL
);
194 frtn
= feeFEEDDecryptBlock(mFeeFeed
,
195 (unsigned char *)cipherText
,
197 (unsigned char *)plainText
,
201 throwCryptKit(frtn
, "feeFEEDDecryptBlock");
203 if(actMoved
> plainTextLen
) {
204 /* Overflow already occurred! */
205 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR
);
207 plainTextLen
= actMoved
;
211 * Additional query size support, necessary because we don't conform to
212 * BlockCryptor's standard one-to-one block scheme
215 #define BUFFER_DEBUG 0
217 #define bprintf(s) printf s
222 size_t CryptKit::FEEDContext::inputSize(
223 size_t outSize
) // input for given output size
226 * We've been assured that this is NOT called for the final() op...
230 inSize
= feeFEEDPlainTextSize(mFeeFeed
, outSize
, 0);
233 inSize
= feeFEEDCipherTextSize(mFeeFeed
, outSize
, 0);
236 /* account for possible pending buffered input */
237 if(inSize
>= inBufSize()) {
238 inSize
-= inBufSize();
241 /* round up to next block size, then lop off one...anything from
242 * blockSize*n to (blockSize*n)-1 has same effect */
243 unsigned inBlocks
= ((inSize
+ inBlockSize()) / inBlockSize());
244 inSize
= (inBlocks
* inBlockSize()) - 1;
245 bprintf(("--- FEEDContext::inputSize inSize 0x%x outSize 0x%x\n",
250 size_t CryptKit::FEEDContext::outputSize(
252 size_t inSize
) // output for given input size
256 rtn
= feeFEEDCipherTextSize(mFeeFeed
, inSize
+ inBufSize(), final
? 1 : 0);
259 rtn
= feeFEEDPlainTextSize(mFeeFeed
, inSize
+ inBufSize(), final
? 1 : 0);
261 bprintf(("--- FEEDContext::outputSize inSize 0x%x outSize 0x%x final %d\n",
262 inSize
, rtn
, final
));
266 void CryptKit::FEEDContext::minimumProgress(
268 size_t &out
) // minimum progress chunks
272 * -- in := one block plaintext
273 * -- out := current cipher size for one block plaintext
276 out
= feeFEEDCipherBufSize(mFeeFeed
, 0);
280 * -- in := current cipher size for one block plaintext
281 * -- out := one block plaintext
283 in
= feeFEEDCipherBufSize(mFeeFeed
, 0);
284 out
= outBlockSize();
288 * Either case - input adjusted for pending. Note inBufSize can be up to one
289 * input block size, leaving the temp result zero here....
291 assert(in
>= inBufSize());
294 /* if it is zero, bump it up so caller can make something happen */
298 bprintf(("--- FEEDContext::minProgres inSize 0x%x outSize 0x%x\n",
303 *** FEEDExp - 2:1 FEED - encrypt n bytes of plaintext, get (roughly) 2n bytes
304 *** of ciphertext. Ciphertext is larger than with FEED, but this is faster.
306 CryptKit::FEEDExpContext::~FEEDExpContext()
309 feeFEEDExpFree(mFeeFeedExp
);
312 if(mFeeKey
&& mAllocdFeeKey
) {
313 feePubKeyFree(mFeeKey
);
319 // called by CSPFullPluginSession; reusable
320 void CryptKit::FEEDExpContext::init(
321 const Context
&context
,
324 if(mInitFlag
&& !opStarted()) {
325 /* reusing - e.g. query followed by encrypt */
329 /* fetch FEE key from context */
330 CSSM_KEYCLASS keyClass
;
334 /* encrypting to public key */
335 keyClass
= CSSM_KEYCLASS_PUBLIC_KEY
;
336 keyUse
= CSSM_KEYUSE_ENCRYPT
;
339 /* decrypting with private key */
340 keyClass
= CSSM_KEYCLASS_PRIVATE_KEY
;
341 keyUse
= CSSM_KEYUSE_DECRYPT
;
343 if(mFeeKey
== NULL
) {
344 assert(!opStarted());
345 mFeeKey
= contextToFeeKey(context
,
356 /* validate context - no other attributes allowed */
357 validateFeedContext(context
);
359 /* OK, looks good. Cook up a feeFEEDExp object. */
360 if(mFeeFeedExp
!= NULL
) {
363 feeFEEDExpFree(mFeeFeedExp
);
366 mFeeFeedExp
= feeFEEDExpNewWithPubKey(mFeeKey
,
369 if(mFeeFeedExp
== NULL
) {
370 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY
);
373 /* finally, have BlockCryptor set up its stuff. */
374 unsigned plainBlockSize
= feeFEEDExpPlainBlockSize(mFeeFeedExp
);
375 unsigned cipherBlockSize
= feeFEEDExpCipherBlockSize(mFeeFeedExp
);
376 setup(encoding
? plainBlockSize
: cipherBlockSize
, // blockSizeIn
377 encoding
? cipherBlockSize
: plainBlockSize
, // blockSizeOut
385 // called by BlockCryptor
386 void CryptKit::FEEDExpContext::encryptBlock(
387 const void *plainText
, // length implied (one block)
390 size_t &cipherTextLen
, // in/out, throws on overflow
396 assert(mFeeFeedExp
!= NULL
);
397 frtn
= feeFEEDExpEncryptBlock(mFeeFeedExp
,
398 (unsigned char *)plainText
,
400 (unsigned char *)cipherText
,
404 throwCryptKit(frtn
, "feeFEEDExpEncryptBlock");
406 if(actMoved
> cipherTextLen
) {
407 /* Overflow already occurred! */
408 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR
);
410 cipherTextLen
= actMoved
;
413 void CryptKit::FEEDExpContext::decryptBlock(
414 const void *cipherText
, // length implied (one cipher block)
416 size_t &plainTextLen
, // in/out, throws on overflow
422 assert(mFeeFeedExp
!= NULL
);
423 frtn
= feeFEEDExpDecryptBlock(mFeeFeedExp
,
424 (unsigned char *)cipherText
,
426 (unsigned char *)plainText
,
430 throwCryptKit(frtn
, "feeFEEDExpDecryptBlock");
432 if(actMoved
> plainTextLen
) {
433 /* Overflow already occurred! */
434 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR
);
436 plainTextLen
= actMoved
;
439 #endif /* CRYPTKIT_CSP_ENABLE */