2 * Copyright (c) 2000-2001,2011,2014 Apple 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.
18 #ifdef BSAFE_CSP_ENABLE
22 // bsafeSymmetric.cpp - symmetric encryption contexts and algorithms
24 #include "bsafecspi.h"
25 #include <security_utilities/debugging.h>
27 #define bbprintf(args...) secinfo("BSafeBuf", ## args)
29 #define VERBOSE_DEBUG 0
40 printf("%s: ", title
);
46 printf("Total Length: %d\n ", d
->Length
);
51 for(i
=0; i
<len
; i
++) {
52 printf("%02X ", d
->Data
[i
]);
60 #define dumpBuf(t, d, m)
61 #endif /* VERBOSE_DEBUG */
63 void BSafe::SymmetricKeyGenContext::generate(
64 const Context
&context
,
68 AppleSymmKeyGenContext::generateSymKey(
75 // We really should match the key algorithm to the en/decrypt
76 // algorithm. Also: verify key usage bits.
77 void BSafe::BlockCipherContext::init(
78 const Context
&context
,
82 bool requirePad
= false;
84 if (reusing(encrypting
))
85 return; // all set to go
87 cssmAlg
= context
.algorithm();
89 // most are handled below; break here to special cases
95 case CSSM_ALGID_3DES_3KEY_EDE
:
102 // Should never have gotten this far
104 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM
);
108 // these variables are used in the switch below and need to
109 // live until after setAlgorithm()
111 B_BLK_CIPHER_W_FEEDBACK_PARAMS spec
;
112 A_RC5_PARAMS rc5Params
;
113 A_RC2_PARAMS rc2Params
;
116 spec
.encryptionParams
= NULL_PTR
; // default, may change
119 spec
.encryptionMethodName
= POINTER("des");
121 case CSSM_ALGID_DESX
:
122 spec
.encryptionMethodName
= POINTER("desx");
124 case CSSM_ALGID_3DES_3KEY_EDE
:
125 spec
.encryptionMethodName
= POINTER("des_ede");
128 spec
.encryptionMethodName
= POINTER("rc5");
129 spec
.encryptionParams
= POINTER(&rc5Params
);
130 rc5Params
.version
= 0x10;
131 // FIXME - get this from context attr
132 rc5Params
.rounds
= 1;
133 rc5Params
.wordSizeInBits
= 32;
137 spec
.encryptionMethodName
= POINTER("rc2");
138 spec
.encryptionParams
= POINTER(&rc2Params
);
139 // effective key size in bits - either from Context,
141 uint32 bits
= context
.getInt(CSSM_ATTRIBUTE_EFFECTIVE_BITS
);
144 CssmKey
&key
= context
.get
<CssmKey
>(CSSM_ATTRIBUTE_KEY
,
145 CSSMERR_CSP_MISSING_ATTR_KEY
);
146 bits
= key
.KeyHeader
.LogicalKeySizeInBits
;
148 rc2Params
.effectiveKeyBits
= bits
;
154 cssmMode
= context
.getInt(CSSM_ATTRIBUTE_MODE
);
156 /* no mode attr --> 0 == CSSM_ALGMODE_NONE, not currently supported */
157 case CSSM_ALGMODE_CBCPadIV8
:
160 case CSSM_ALGMODE_CBC_IV8
:
162 iv
= context
.get
<CssmData
>(CSSM_ATTRIBUTE_INIT_VECTOR
,
163 CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR
);
164 spec
.feedbackMethodName
= POINTER("cbc");
165 spec
.feedbackParams
= POINTER(&iv
);
169 case CSSM_ALGMODE_OFB_IV8
: {
170 iv
= context
.get
<CssmData
>(CSSM_ATTRIBUTE_INIT_VECTOR
,
171 CSSMERR_CSP_MISSING_ATTR_INIT_VECTOR
);
172 spec
.feedbackMethodName
= POINTER("ofb");
173 spec
.feedbackParams
= POINTER(&iv
);
177 case CSSM_ALGMODE_ECB
: {
178 spec
.feedbackMethodName
= POINTER("ecb");
179 spec
.feedbackParams
= POINTER(&blockSize
);
183 errorLog1("BSafe symmetric init: illegal mode (%d)\n", (int)cssmMode
);
184 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_MODE
);
188 spec
.paddingParams
= NULL_PTR
;
189 /* no padding attr --> 0 == PADDING_NONE */
191 uint32 cssmPadding
= context
.getInt(CSSM_ATTRIBUTE_PADDING
);
193 switch(cssmPadding
) {
194 case CSSM_PADDING_PKCS1
: // for backwards compatibility
195 case CSSM_PADDING_PKCS5
:
196 case CSSM_PADDING_PKCS7
:
197 spec
.paddingMethodName
= POINTER("pad");
201 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING
);
205 if(cssmPadding
!= CSSM_PADDING_NONE
) {
206 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING
);
209 spec
.paddingMethodName
= POINTER("nopad");
213 // put it all together
214 setAlgorithm(AI_FeedbackCipher
, &spec
); // set BSafe algorithm
215 setKeyFromContext(context
); // set BSafe key
216 cipherInit(); // common cryption init
219 void BSafe::BlockCipherContext::RC4init(
220 const Context
&context
)
222 setAlgorithm(AI_RC4
, NULL
); // set BSafe algorithm
223 setKeyFromContext(context
); // set BSafe key
225 cipherInit(); // common cryption init
228 void BSafe::BlockCipherContext::trackUpdate(size_t inSize
, size_t outSize
)
230 size_t newPending
= pending
+ inSize
;
231 pending
= newPending
% blockSize
;
234 * Most of the time, the max size buffered by BSAFE is
235 * blockSize - 1 bytes. When decrypting and padding is enabled,
236 * BSAFE buffers up to a full block.
238 if(!mDirection
&& //Êdecrypting
239 padEnable
&& // padding
240 (pending
== 0) && // mod result was 0
241 (newPending
> 0)) { // but nonzero total
242 /* BSAFE is holding a whole block in its buffer */
245 bbprintf("===trackUpdte: %s; inSize=%d newPending=%d pending=%d",
246 (mDirection
? "encrypt" : "decrypt"),
247 inSize
, newPending
, pending
);
250 size_t BSafe::BlockCipherContext::inputSize(size_t outSize
)
252 // if we have an 'outSize' output buffer, how many input bytes may we feed in?
253 size_t wholeBlocks
= outSize
/ blockSize
;
254 return wholeBlocks
* blockSize
- pending
+ (blockSize
- 1);
257 size_t BSafe::BlockCipherContext::outputSize(bool final
, size_t inSize
)
259 // how much output buffer will we need for 'size' input bytes?
261 size_t totalToGo
= inSize
+ pending
;
262 // total to go, rounded up to next block
263 size_t numBlocks
= (totalToGo
+ blockSize
- 1) / blockSize
;
267 * encrypting: may get one additional block on final() if padding
268 * decrypting: outsize always <= insize
270 if(mDirection
&& // encrypting
271 final
&& // last time
272 padEnable
&& // padding enabled
273 ((totalToGo
% blockSize
) == 0)) { // even ptext len
274 numBlocks
++; // extra pad block
276 outSize
= numBlocks
* blockSize
;
277 bbprintf("===outputSize: %s; final=%d inSize=%d pending=%d outSize=%d",
278 (mDirection
? "encrypt" : "decrypt"),
279 final
, inSize
, pending
, outSize
);
283 void BSafe::BlockCipherContext::minimumProgress(size_t &inSize
, size_t &outSize
)
285 // eat up buffer, proceed one full block
286 inSize
= blockSize
- pending
;
289 #endif /* BSAFE_CSP_ENABLE */