]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_smime/lib/cmscipher.c
Security-58286.200.222.tar.gz
[apple/security.git] / OSX / libsecurity_smime / lib / cmscipher.c
1 /*
2 * The contents of this file are subject to the Mozilla Public
3 * License Version 1.1 (the "License"); you may not use this file
4 * except in compliance with the License. You may obtain a copy of
5 * the License at http://www.mozilla.org/MPL/
6 *
7 * Software distributed under the License is distributed on an "AS
8 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9 * implied. See the License for the specific language governing
10 * rights and limitations under the License.
11 *
12 * The Original Code is the Netscape security libraries.
13 *
14 * The Initial Developer of the Original Code is Netscape
15 * Communications Corporation. Portions created by Netscape are
16 * Copyright (C) 1994-2000 Netscape Communications Corporation. All
17 * Rights Reserved.
18 *
19 * Contributor(s):
20 *
21 * Alternatively, the contents of this file may be used under the
22 * terms of the GNU General Public License Version 2 or later (the
23 * "GPL"), in which case the provisions of the GPL are applicable
24 * instead of those above. If you wish to allow use of your
25 * version of this file only under the terms of the GPL and not to
26 * allow others to use your version of this file under the MPL,
27 * indicate your decision by deleting the provisions above and
28 * replace them with the notice and other provisions required by
29 * the GPL. If you do not delete the provisions above, a recipient
30 * may use your version of this file under either the MPL or the
31 * GPL.
32 */
33
34 /*
35 * Encryption/decryption routines for CMS implementation, none of which are exported.
36 *
37 */
38
39 #include "cmslocal.h"
40
41 #include "secoid.h"
42 #include <security_asn1/secerr.h>
43 #include <security_asn1/secasn1.h>
44 #include <Security/SecAsn1Templates.h>
45 #include <Security/cssmapi.h>
46 #include <Security/cssmapple.h>
47 #include <Security/SecKeyPriv.h>
48
49 /*
50 * -------------------------------------------------------------------
51 * Cipher stuff.
52 */
53
54 #if 0
55 typedef OSStatus (*nss_cms_cipher_function) (void *, unsigned char *, unsigned int *,
56 unsigned int, const unsigned char *, unsigned int);
57 typedef OSStatus (*nss_cms_cipher_destroy) (void *, Boolean);
58 #endif
59
60 #define BLOCK_SIZE 4096
61
62 struct SecCmsCipherContextStr {
63 #if 1
64 CSSM_CC_HANDLE cc; /* CSP CONTEXT */
65 Boolean encrypt; /* encrypt / decrypt switch */
66 #else
67 void * cx; /* PK11 cipher context */
68 nss_cms_cipher_function doit;
69 nss_cms_cipher_destroy destroy;
70 Boolean encrypt; /* encrypt / decrypt switch */
71 int block_size; /* block & pad sizes for cipher */
72 int pad_size;
73 int pending_count; /* pending data (not yet en/decrypted */
74 unsigned char pending_buf[BLOCK_SIZE];/* because of blocking */
75 #endif
76 };
77
78 typedef struct sec_rc2cbcParameterStr {
79 SECItem rc2ParameterVersion;
80 SECItem iv;
81 } sec_rc2cbcParameter;
82
83 static const SecAsn1Template sec_rc2cbc_parameter_template[] = {
84 { SEC_ASN1_SEQUENCE,
85 0, NULL, sizeof(sec_rc2cbcParameter) },
86 { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT,
87 offsetof(sec_rc2cbcParameter,rc2ParameterVersion) },
88 { SEC_ASN1_OCTET_STRING,
89 offsetof(sec_rc2cbcParameter,iv) },
90 { 0 }
91 };
92
93 /*
94 ** Convert a der encoded *signed* integer into a machine integral value.
95 ** If an underflow/overflow occurs, sets error code and returns min/max.
96 */
97 static long
98 DER_GetInteger(SECItem *it)
99 {
100 long ival = 0;
101 CSSM_SIZE len = it->Length;
102 unsigned char *cp = it->Data;
103 unsigned long overflow = 0x1ffUL << (((sizeof(ival) - 1) * 8) - 1);
104 unsigned long ofloinit;
105
106 if (*cp & 0x80)
107 ival = -1L;
108 ofloinit = ival & overflow;
109
110 while (len) {
111 if ((ival & overflow) != ofloinit) {
112 PORT_SetError(SEC_ERROR_BAD_DER);
113 if (ival < 0) {
114 return LONG_MIN;
115 }
116 return LONG_MAX;
117 }
118 ival = ival << 8;
119 ival |= *cp++;
120 --len;
121 }
122 return ival;
123 }
124
125 /* S/MIME picked id values to represent differnt keysizes */
126 /* I do have a formula, but it ain't pretty, and it only works because you
127 * can always match three points to a parabola:) */
128 static unsigned char rc2_map(SECItem *version)
129 {
130 long x;
131
132 x = DER_GetInteger(version);
133
134 switch (x) {
135 case 58: return 128;
136 case 120: return 64;
137 case 160: return 40;
138 }
139 return 128;
140 }
141
142 static unsigned long rc2_unmap(unsigned long x)
143 {
144 switch (x) {
145 case 128: return 58;
146 case 64: return 120;
147 case 40: return 160;
148 }
149 return 58;
150 }
151
152 /* default IV size in bytes */
153 #define DEFAULT_IV_SIZE 8
154 /* IV/block size for AES */
155 #define AES_BLOCK_SIZE 16
156 /* max IV size in bytes */
157 #define MAX_IV_SIZE AES_BLOCK_SIZE
158
159 static SecCmsCipherContextRef
160 SecCmsCipherContextStart(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorithmID *algid, Boolean encrypt)
161 {
162 SecCmsCipherContextRef cc;
163 CSSM_CC_HANDLE ciphercc = 0;
164 SECOidData *oidData;
165 SECOidTag algtag;
166 CSSM_ALGORITHMS algorithm;
167 CSSM_PADDING padding = CSSM_PADDING_PKCS7;
168 CSSM_ENCRYPT_MODE mode;
169 CSSM_CSP_HANDLE cspHandle;
170 const CSSM_KEY *cssmKey;
171 OSStatus rv;
172 uint8 ivbuf[MAX_IV_SIZE];
173 CSSM_DATA initVector = { DEFAULT_IV_SIZE, ivbuf };
174 //CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_ALG_PARAMS, sizeof(CSSM_DATA_PTR) };
175
176 rv = SecKeyGetCSPHandle(key, &cspHandle);
177 if (rv)
178 goto loser;
179 rv = SecKeyGetCSSMKey(key, &cssmKey);
180 if (rv)
181 goto loser;
182
183 // @@@ Add support for PBE based stuff
184
185 oidData = SECOID_FindOID(&algid->algorithm);
186 if (!oidData)
187 goto loser;
188 algtag = oidData->offset;
189 algorithm = oidData->cssmAlgorithm;
190 if (!algorithm)
191 goto loser;
192
193 switch (algtag)
194 {
195 case SEC_OID_RC2_CBC:
196 case SEC_OID_RC4:
197 case SEC_OID_DES_EDE3_CBC:
198 case SEC_OID_DES_EDE:
199 case SEC_OID_DES_CBC:
200 case SEC_OID_RC5_CBC_PAD:
201 case SEC_OID_FORTEZZA_SKIPJACK:
202 mode = CSSM_ALGMODE_CBCPadIV8;
203 break;
204
205 /* RFC 3565 says that these sizes refer to key size, NOT block size */
206 case SEC_OID_AES_128_CBC:
207 case SEC_OID_AES_192_CBC:
208 case SEC_OID_AES_256_CBC:
209 initVector.Length = AES_BLOCK_SIZE;
210 mode = CSSM_ALGMODE_CBCPadIV8;
211 break;
212
213 case SEC_OID_DES_ECB:
214 case SEC_OID_AES_128_ECB:
215 case SEC_OID_AES_192_ECB:
216 case SEC_OID_AES_256_ECB:
217 mode = CSSM_ALGMODE_ECBPad;
218 break;
219
220 case SEC_OID_DES_OFB:
221 mode = CSSM_ALGMODE_OFBPadIV8;
222 break;
223
224 case SEC_OID_DES_CFB:
225 mode = CSSM_ALGMODE_CFBPadIV8;
226 break;
227
228 default:
229 goto loser;
230 }
231
232 if (encrypt)
233 {
234 CSSM_CC_HANDLE randomcc;
235 //SECItem *parameters;
236
237 // Generate random initVector
238 if (CSSM_CSP_CreateRandomGenContext(cspHandle,
239 CSSM_ALGID_APPLE_YARROW,
240 NULL, /* seed*/
241 initVector.Length,
242 &randomcc))
243 goto loser;
244
245 if (CSSM_GenerateRandom(randomcc, &initVector))
246 goto loser;
247 CSSM_DeleteContext(randomcc);
248
249 // Put IV into algid.parameters
250 switch (algtag)
251 {
252 case SEC_OID_RC4:
253 case SEC_OID_DES_EDE3_CBC:
254 case SEC_OID_DES_EDE:
255 case SEC_OID_DES_CBC:
256 case SEC_OID_AES_128_CBC:
257 case SEC_OID_AES_192_CBC:
258 case SEC_OID_AES_256_CBC:
259 case SEC_OID_FORTEZZA_SKIPJACK:
260 case SEC_OID_DES_ECB:
261 case SEC_OID_AES_128_ECB:
262 case SEC_OID_AES_192_ECB:
263 case SEC_OID_AES_256_ECB:
264 case SEC_OID_DES_OFB:
265 case SEC_OID_DES_CFB:
266 /* Just encode the initVector as an octet string. */
267 if (!SEC_ASN1EncodeItem(poolp, &algid->parameters,
268 &initVector, kSecAsn1OctetStringTemplate))
269 goto loser;
270 break;
271
272 case SEC_OID_RC2_CBC:
273 {
274 sec_rc2cbcParameter rc2 = {};
275 unsigned long rc2version;
276 SECItem *newParams;
277
278 rc2.iv = initVector;
279 rc2version = rc2_unmap(cssmKey->KeyHeader.LogicalKeySizeInBits);
280 if (!SEC_ASN1EncodeUnsignedInteger (NULL, &(rc2.rc2ParameterVersion),
281 rc2version))
282 goto loser;
283 newParams = SEC_ASN1EncodeItem (poolp, &algid->parameters, &rc2,
284 sec_rc2cbc_parameter_template);
285 PORT_Free(rc2.rc2ParameterVersion.Data);
286 rc2.rc2ParameterVersion.Data = NULL;
287 if (newParams == NULL)
288 goto loser;
289 break;
290 }
291 case SEC_OID_RC5_CBC_PAD:
292 default:
293 // @@@ Implement rc5 params stuff.
294 goto loser;
295 break;
296 }
297 }
298 else
299 {
300 // Extract IV from algid.parameters
301 // Put IV into algid.parameters
302 switch (algtag)
303 {
304 case SEC_OID_RC4:
305 case SEC_OID_DES_EDE3_CBC:
306 case SEC_OID_DES_EDE:
307 case SEC_OID_DES_CBC:
308 case SEC_OID_AES_128_CBC:
309 case SEC_OID_AES_192_CBC:
310 case SEC_OID_AES_256_CBC:
311 case SEC_OID_FORTEZZA_SKIPJACK:
312 case SEC_OID_DES_ECB:
313 case SEC_OID_AES_128_ECB:
314 case SEC_OID_AES_192_ECB:
315 case SEC_OID_AES_256_ECB:
316 case SEC_OID_DES_OFB:
317 case SEC_OID_DES_CFB:
318 {
319 CSSM_DATA iv = {};
320 /* Just decode the initVector from an octet string. */
321 rv = SEC_ASN1DecodeItem(NULL, &iv, kSecAsn1OctetStringTemplate, &(algid->parameters));
322 if (rv)
323 goto loser;
324 if (initVector.Length != iv.Length) {
325 PORT_Free(iv.Data);
326 iv.Data = NULL;
327 goto loser;
328 }
329 memcpy(initVector.Data, iv.Data, initVector.Length);
330 PORT_Free(iv.Data);
331 iv.Data = NULL;
332 break;
333 }
334 case SEC_OID_RC2_CBC:
335 {
336 sec_rc2cbcParameter rc2 = {};
337 unsigned long ulEffectiveBits;
338
339 rv = SEC_ASN1DecodeItem(NULL, &rc2 ,sec_rc2cbc_parameter_template,
340 &(algid->parameters));
341 if (rv)
342 goto loser;
343
344 if (initVector.Length != rc2.iv.Length) {
345 PORT_Free(rc2.iv.Data);
346 rc2.iv.Data = NULL;
347 PORT_Free(rc2.rc2ParameterVersion.Data);
348 rc2.rc2ParameterVersion.Data = NULL;
349 goto loser;
350 }
351 memcpy(initVector.Data, rc2.iv.Data, initVector.Length);
352 PORT_Free(rc2.iv.Data);
353 rc2.iv.Data = NULL;
354
355 ulEffectiveBits = rc2_map(&rc2.rc2ParameterVersion);
356 PORT_Free(rc2.rc2ParameterVersion.Data);
357 rc2.rc2ParameterVersion.Data = NULL;
358 if (ulEffectiveBits != cssmKey->KeyHeader.LogicalKeySizeInBits)
359 goto loser;
360 break;
361 }
362 case SEC_OID_RC5_CBC_PAD:
363 default:
364 // @@@ Implement rc5 params stuff.
365 goto loser;
366 break;
367 }
368 }
369
370 if (CSSM_CSP_CreateSymmetricContext(cspHandle,
371 algorithm,
372 mode,
373 NULL, /* accessCred */
374 cssmKey,
375 &initVector,
376 padding,
377 NULL, /* reserved */
378 &ciphercc))
379 goto loser;
380
381 if (encrypt)
382 rv = CSSM_EncryptDataInit(ciphercc);
383 else
384 rv = CSSM_DecryptDataInit(ciphercc);
385 if (rv)
386 goto loser;
387
388 cc = (SecCmsCipherContextRef)PORT_ZAlloc(sizeof(SecCmsCipherContext));
389 if (cc == NULL)
390 goto loser;
391
392 cc->cc = ciphercc;
393 cc->encrypt = encrypt;
394
395 return cc;
396 loser:
397 if (ciphercc)
398 CSSM_DeleteContext(ciphercc);
399
400 return NULL;
401 }
402
403 /*
404 * SecCmsCipherContextStartDecrypt - create a cipher context to do decryption
405 * based on the given bulk * encryption key and algorithm identifier (which may include an iv).
406 *
407 * XXX Once both are working, it might be nice to combine this and the
408 * function below (for starting up encryption) into one routine, and just
409 * have two simple cover functions which call it.
410 */
411 SecCmsCipherContextRef
412 SecCmsCipherContextStartDecrypt(SecSymmetricKeyRef key, SECAlgorithmID *algid)
413 {
414 return SecCmsCipherContextStart(NULL, key, algid, PR_FALSE);
415 #if 0
416 SecCmsCipherContextRef cc;
417 void *ciphercx;
418 CK_MECHANISM_TYPE mechanism;
419 CSSM_DATA_PTR param;
420 PK11SlotInfo *slot;
421 SECOidTag algtag;
422
423 algtag = SECOID_GetAlgorithmTag(algid);
424
425 /* set param and mechanism */
426 if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
427 CK_MECHANISM pbeMech, cryptoMech;
428 CSSM_DATA_PTR pbeParams;
429 SEC_PKCS5KeyAndPassword *keyPwd;
430
431 PORT_Memset(&pbeMech, 0, sizeof(CK_MECHANISM));
432 PORT_Memset(&cryptoMech, 0, sizeof(CK_MECHANISM));
433
434 /* HACK ALERT!
435 * in this case, key is not actually a SecSymmetricKeyRef, but a SEC_PKCS5KeyAndPassword *
436 */
437 keyPwd = (SEC_PKCS5KeyAndPassword *)key;
438 key = keyPwd->key;
439
440 /* find correct PK11 mechanism and parameters to initialize pbeMech */
441 pbeMech.mechanism = PK11_AlgtagToMechanism(algtag);
442 pbeParams = PK11_ParamFromAlgid(algid);
443 if (!pbeParams)
444 return NULL;
445 pbeMech.pParameter = pbeParams->Data;
446 pbeMech.ulParameterLen = pbeParams->Length;
447
448 /* now map pbeMech to cryptoMech */
449 if (PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, keyPwd->pwitem,
450 PR_FALSE) != CKR_OK) {
451 SECITEM_ZfreeItem(pbeParams, PR_TRUE);
452 return NULL;
453 }
454 SECITEM_ZfreeItem(pbeParams, PR_TRUE);
455
456 /* and use it to initialize param & mechanism */
457 if ((param = (CSSM_DATA_PTR)PORT_ZAlloc(sizeof(CSSM_DATA))) == NULL)
458 return NULL;
459
460 param->Data = (unsigned char *)cryptoMech.pParameter;
461 param->Length = cryptoMech.ulParameterLen;
462 mechanism = cryptoMech.mechanism;
463 } else {
464 mechanism = PK11_AlgtagToMechanism(algtag);
465 if ((param = PK11_ParamFromAlgid(algid)) == NULL)
466 return NULL;
467 }
468
469 cc = (SecCmsCipherContextRef)PORT_ZAlloc(sizeof(SecCmsCipherContext));
470 if (cc == NULL) {
471 SECITEM_FreeItem(param,PR_TRUE);
472 return NULL;
473 }
474
475 /* figure out pad and block sizes */
476 cc->pad_size = PK11_GetBlockSize(mechanism, param);
477 slot = PK11_GetSlotFromKey(key);
478 cc->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : cc->pad_size;
479 PK11_FreeSlot(slot);
480
481 /* create PK11 cipher context */
482 ciphercx = PK11_CreateContextBySymKey(mechanism, CKA_DECRYPT, key, param);
483 SECITEM_FreeItem(param, PR_TRUE);
484 if (ciphercx == NULL) {
485 PORT_Free (cc);
486 return NULL;
487 }
488
489 cc->cx = ciphercx;
490 cc->doit = (nss_cms_cipher_function) PK11_CipherOp;
491 cc->destroy = (nss_cms_cipher_destroy) PK11_DestroyContext;
492 cc->encrypt = PR_FALSE;
493 cc->pending_count = 0;
494
495 return cc;
496 #endif
497 }
498
499 /*
500 * SecCmsCipherContextStartEncrypt - create a cipher object to do encryption,
501 * based on the given bulk encryption key and algorithm tag. Fill in the algorithm
502 * identifier (which may include an iv) appropriately.
503 *
504 * XXX Once both are working, it might be nice to combine this and the
505 * function above (for starting up decryption) into one routine, and just
506 * have two simple cover functions which call it.
507 */
508 SecCmsCipherContextRef
509 SecCmsCipherContextStartEncrypt(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorithmID *algid)
510 {
511 return SecCmsCipherContextStart(poolp, key, algid, PR_TRUE);
512 #if 0
513 SecCmsCipherContextRef cc;
514 void *ciphercx;
515 CSSM_DATA_PTR param;
516 OSStatus rv;
517 CK_MECHANISM_TYPE mechanism;
518 PK11SlotInfo *slot;
519 Boolean needToEncodeAlgid = PR_FALSE;
520 SECOidTag algtag = SECOID_GetAlgorithmTag(algid);
521
522 /* set param and mechanism */
523 if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
524 CK_MECHANISM pbeMech, cryptoMech;
525 CSSM_DATA_PTR pbeParams;
526 SEC_PKCS5KeyAndPassword *keyPwd;
527
528 PORT_Memset(&pbeMech, 0, sizeof(CK_MECHANISM));
529 PORT_Memset(&cryptoMech, 0, sizeof(CK_MECHANISM));
530
531 /* HACK ALERT!
532 * in this case, key is not actually a SecSymmetricKeyRef, but a SEC_PKCS5KeyAndPassword *
533 */
534 keyPwd = (SEC_PKCS5KeyAndPassword *)key;
535 key = keyPwd->key;
536
537 /* find correct PK11 mechanism and parameters to initialize pbeMech */
538 pbeMech.mechanism = PK11_AlgtagToMechanism(algtag);
539 pbeParams = PK11_ParamFromAlgid(algid);
540 if (!pbeParams)
541 return NULL;
542 pbeMech.pParameter = pbeParams->Data;
543 pbeMech.ulParameterLen = pbeParams->Length;
544
545 /* now map pbeMech to cryptoMech */
546 if (PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, keyPwd->pwitem,
547 PR_FALSE) != CKR_OK) {
548 SECITEM_ZfreeItem(pbeParams, PR_TRUE);
549 return NULL;
550 }
551 SECITEM_ZfreeItem(pbeParams, PR_TRUE);
552
553 /* and use it to initialize param & mechanism */
554 if ((param = (CSSM_DATA_PTR)PORT_ZAlloc(sizeof(CSSM_DATA))) == NULL)
555 return NULL;
556
557 param->Data = (unsigned char *)cryptoMech.pParameter;
558 param->Length = cryptoMech.ulParameterLen;
559 mechanism = cryptoMech.mechanism;
560 } else {
561 mechanism = PK11_AlgtagToMechanism(algtag);
562 if ((param = PK11_GenerateNewParam(mechanism, key)) == NULL)
563 return NULL;
564 needToEncodeAlgid = PR_TRUE;
565 }
566
567 cc = (SecCmsCipherContextRef)PORT_ZAlloc(sizeof(SecCmsCipherContext));
568 if (cc == NULL)
569 return NULL;
570
571 /* now find pad and block sizes for our mechanism */
572 cc->pad_size = PK11_GetBlockSize(mechanism,param);
573 slot = PK11_GetSlotFromKey(key);
574 cc->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : cc->pad_size;
575 PK11_FreeSlot(slot);
576
577 /* and here we go, creating a PK11 cipher context */
578 ciphercx = PK11_CreateContextBySymKey(mechanism, CKA_ENCRYPT, key, param);
579 if (ciphercx == NULL) {
580 PORT_Free(cc);
581 cc = NULL;
582 goto loser;
583 }
584
585 /*
586 * These are placed after the CreateContextBySymKey() because some
587 * mechanisms have to generate their IVs from their card (i.e. FORTEZZA).
588 * Don't move it from here.
589 * XXX is that right? the purpose of this is to get the correct algid
590 * containing the IVs etc. for encoding. this means we need to set this up
591 * BEFORE encoding the algid in the contentInfo, right?
592 */
593 if (needToEncodeAlgid) {
594 rv = PK11_ParamToAlgid(algtag, param, poolp, algid);
595 if(rv != SECSuccess) {
596 PORT_Free(cc);
597 cc = NULL;
598 goto loser;
599 }
600 }
601
602 cc->cx = ciphercx;
603 cc->doit = (nss_cms_cipher_function)PK11_CipherOp;
604 cc->destroy = (nss_cms_cipher_destroy)PK11_DestroyContext;
605 cc->encrypt = PR_TRUE;
606 cc->pending_count = 0;
607
608 loser:
609 SECITEM_FreeItem(param, PR_TRUE);
610
611 return cc;
612 #endif
613 }
614
615 void
616 SecCmsCipherContextDestroy(SecCmsCipherContextRef cc)
617 {
618 PORT_Assert(cc != NULL);
619 if (cc == NULL)
620 return;
621 CSSM_DeleteContext(cc->cc);
622 PORT_Free(cc);
623 }
624
625 static unsigned int
626 SecCmsCipherContextLength(SecCmsCipherContextRef cc, unsigned int input_len, Boolean final, Boolean encrypt)
627 {
628 CSSM_QUERY_SIZE_DATA dataBlockSize[2] = { { input_len, 0 }, { input_len, 0 } };
629 /* Hack CDSA treats the last block as the final one. So unless we are being asked to report the final size we ask for 2 block and ignore the second (final) one. */
630 OSStatus rv = CSSM_QuerySize(cc->cc, cc->encrypt, final ? 1 : 2, dataBlockSize);
631 if (rv)
632 {
633 PORT_SetError(rv);
634 return 0;
635 }
636
637 return dataBlockSize[0].SizeOutputBlock;
638 }
639
640 /*
641 * SecCmsCipherContextDecryptLength - find the output length of the next call to decrypt.
642 *
643 * cc - the cipher context
644 * input_len - number of bytes used as input
645 * final - true if this is the final chunk of data
646 *
647 * Result can be used to perform memory allocations. Note that the amount
648 * is exactly accurate only when not doing a block cipher or when final
649 * is false, otherwise it is an upper bound on the amount because until
650 * we see the data we do not know how many padding bytes there are
651 * (always between 1 and bsize).
652 *
653 * Note that this can return zero, which does not mean that the decrypt
654 * operation can be skipped! (It simply means that there are not enough
655 * bytes to make up an entire block; the bytes will be reserved until
656 * there are enough to encrypt/decrypt at least one block.) However,
657 * if zero is returned it *does* mean that no output buffer need be
658 * passed in to the subsequent decrypt operation, as no output bytes
659 * will be stored.
660 */
661 size_t
662 SecCmsCipherContextDecryptLength(SecCmsCipherContextRef cc, size_t input_len, Boolean final)
663 {
664 #if 1
665 return SecCmsCipherContextLength(cc, (unsigned int)input_len, final, PR_FALSE);
666 #else
667 int blocks, block_size;
668
669 PORT_Assert (! cc->encrypt);
670
671 block_size = cc->block_size;
672
673 /*
674 * If this is not a block cipher, then we always have the same
675 * number of output bytes as we had input bytes.
676 */
677 if (block_size == 0)
678 return input_len;
679
680 /*
681 * On the final call, we will always use up all of the pending
682 * bytes plus all of the input bytes, *but*, there will be padding
683 * at the end and we cannot predict how many bytes of padding we
684 * will end up removing. The amount given here is actually known
685 * to be at least 1 byte too long (because we know we will have
686 * at least 1 byte of padding), but seemed clearer/better to me.
687 */
688 if (final)
689 return cc->pending_count + input_len;
690
691 /*
692 * Okay, this amount is exactly what we will output on the
693 * next cipher operation. We will always hang onto the last
694 * 1 - block_size bytes for non-final operations. That is,
695 * we will do as many complete blocks as we can *except* the
696 * last block (complete or partial). (This is because until
697 * we know we are at the end, we cannot know when to interpret
698 * and removing the padding byte(s), which are guaranteed to
699 * be there.)
700 */
701 blocks = (cc->pending_count + input_len - 1) / block_size;
702 return blocks * block_size;
703 #endif
704 }
705
706 /*
707 * SecCmsCipherContextEncryptLength - find the output length of the next call to encrypt.
708 *
709 * cc - the cipher context
710 * input_len - number of bytes used as input
711 * final - true if this is the final chunk of data
712 *
713 * Result can be used to perform memory allocations.
714 *
715 * Note that this can return zero, which does not mean that the encrypt
716 * operation can be skipped! (It simply means that there are not enough
717 * bytes to make up an entire block; the bytes will be reserved until
718 * there are enough to encrypt/decrypt at least one block.) However,
719 * if zero is returned it *does* mean that no output buffer need be
720 * passed in to the subsequent encrypt operation, as no output bytes
721 * will be stored.
722 */
723 size_t
724 SecCmsCipherContextEncryptLength(SecCmsCipherContextRef cc, size_t input_len, Boolean final)
725 {
726 #if 1
727 return SecCmsCipherContextLength(cc, (unsigned int)input_len, final, PR_TRUE);
728 #else
729 int blocks, block_size;
730 int pad_size;
731
732 PORT_Assert (cc->encrypt);
733
734 block_size = cc->block_size;
735 pad_size = cc->pad_size;
736
737 /*
738 * If this is not a block cipher, then we always have the same
739 * number of output bytes as we had input bytes.
740 */
741 if (block_size == 0)
742 return input_len;
743
744 /*
745 * On the final call, we only send out what we need for
746 * remaining bytes plus the padding. (There is always padding,
747 * so even if we have an exact number of blocks as input, we
748 * will add another full block that is just padding.)
749 */
750 if (final) {
751 if (pad_size == 0) {
752 return cc->pending_count + input_len;
753 } else {
754 blocks = (cc->pending_count + input_len) / pad_size;
755 blocks++;
756 return blocks*pad_size;
757 }
758 }
759
760 /*
761 * Now, count the number of complete blocks of data we have.
762 */
763 blocks = (cc->pending_count + input_len) / block_size;
764
765
766 return blocks * block_size;
767 #endif
768 }
769
770
771 static OSStatus
772 SecCmsCipherContextCrypt(SecCmsCipherContextRef cc, unsigned char *output,
773 size_t *output_len_p, size_t max_output_len,
774 const unsigned char *input, size_t input_len,
775 Boolean final, Boolean encrypt)
776 {
777 CSSM_DATA outputBuf = { max_output_len, output };
778 CSSM_SIZE bytes_output = 0;
779 OSStatus rv = 0;
780
781 if (input_len)
782 {
783 CSSM_DATA inputBuf = { input_len, (uint8 *)input };
784
785 if (encrypt)
786 rv = CSSM_EncryptDataUpdate(cc->cc, &inputBuf, 1, &outputBuf, 1, &bytes_output);
787 else
788 rv = CSSM_DecryptDataUpdate(cc->cc, &inputBuf, 1, &outputBuf, 1, &bytes_output);
789 }
790
791 if (!rv && final)
792 {
793 CSSM_DATA remainderBuf = { max_output_len - bytes_output, output + bytes_output };
794 if (encrypt)
795 rv = CSSM_EncryptDataFinal(cc->cc, &remainderBuf);
796 else
797 rv = CSSM_DecryptDataFinal(cc->cc, &remainderBuf);
798
799 bytes_output += remainderBuf.Length;
800 }
801
802 if (rv)
803 PORT_SetError(SEC_ERROR_BAD_DATA);
804 else if (output_len_p)
805 *output_len_p = bytes_output;
806
807 return rv;
808 }
809
810 /*
811 * SecCmsCipherContextDecrypt - do the decryption
812 *
813 * cc - the cipher context
814 * output - buffer for decrypted result bytes
815 * output_len_p - number of bytes in output
816 * max_output_len - upper bound on bytes to put into output
817 * input - pointer to input bytes
818 * input_len - number of input bytes
819 * final - true if this is the final chunk of data
820 *
821 * Decrypts a given length of input buffer (starting at "input" and
822 * containing "input_len" bytes), placing the decrypted bytes in
823 * "output" and storing the output length in "*output_len_p".
824 * "cc" is the return value from SecCmsCipherStartDecrypt.
825 * When "final" is true, this is the last of the data to be decrypted.
826 *
827 * This is much more complicated than it sounds when the cipher is
828 * a block-type, meaning that the decryption function will only
829 * operate on whole blocks. But our caller is operating stream-wise,
830 * and can pass in any number of bytes. So we need to keep track
831 * of block boundaries. We save excess bytes between calls in "cc".
832 * We also need to determine which bytes are padding, and remove
833 * them from the output. We can only do this step when we know we
834 * have the final block of data. PKCS #7 specifies that the padding
835 * used for a block cipher is a string of bytes, each of whose value is
836 * the same as the length of the padding, and that all data is padded.
837 * (Even data that starts out with an exact multiple of blocks gets
838 * added to it another block, all of which is padding.)
839 */
840 OSStatus
841 SecCmsCipherContextDecrypt(SecCmsCipherContextRef cc, unsigned char *output,
842 size_t *output_len_p, size_t max_output_len,
843 const unsigned char *input, size_t input_len,
844 Boolean final)
845 {
846 #if 1
847 return SecCmsCipherContextCrypt(cc, output,
848 output_len_p, max_output_len,
849 input, input_len,
850 final, PR_FALSE);
851 #else
852 int blocks, bsize, pcount, padsize;
853 unsigned int max_needed, ifraglen, ofraglen, output_len;
854 unsigned char *pbuf;
855 OSStatus rv;
856
857 PORT_Assert (! cc->encrypt);
858
859 /*
860 * Check that we have enough room for the output. Our caller should
861 * already handle this; failure is really an internal error (i.e. bug).
862 */
863 max_needed = SecCmsCipherContextDecryptLength(cc, input_len, final);
864 PORT_Assert (max_output_len >= max_needed);
865 if (max_output_len < max_needed) {
866 /* PORT_SetError (XXX); */
867 return SECFailure;
868 }
869
870 /*
871 * hardware encryption does not like small decryption sizes here, so we
872 * allow both blocking and padding.
873 */
874 bsize = cc->block_size;
875 padsize = cc->pad_size;
876
877 /*
878 * When no blocking or padding work to do, we can simply call the
879 * cipher function and we are done.
880 */
881 if (bsize == 0) {
882 return (* cc->doit) (cc->cx, output, output_len_p, max_output_len,
883 input, input_len);
884 }
885
886 pcount = cc->pending_count;
887 pbuf = cc->pending_buf;
888
889 output_len = 0;
890
891 if (pcount) {
892 /*
893 * Try to fill in an entire block, starting with the bytes
894 * we already have saved away.
895 */
896 while (input_len && pcount < bsize) {
897 pbuf[pcount++] = *input++;
898 input_len--;
899 }
900 /*
901 * If we have at most a whole block and this is not our last call,
902 * then we are done for now. (We do not try to decrypt a lone
903 * single block because we cannot interpret the padding bytes
904 * until we know we are handling the very last block of all input.)
905 */
906 if (input_len == 0 && !final) {
907 cc->pending_count = pcount;
908 if (output_len_p)
909 *output_len_p = 0;
910 return SECSuccess;
911 }
912 /*
913 * Given the logic above, we expect to have a full block by now.
914 * If we do not, there is something wrong, either with our own
915 * logic or with (length of) the data given to us.
916 */
917 if ((padsize != 0) && (pcount % padsize) != 0) {
918 PORT_Assert (final);
919 PORT_SetError (SEC_ERROR_BAD_DATA);
920 return SECFailure;
921 }
922 /*
923 * Decrypt the block.
924 */
925 rv = (*cc->doit)(cc->cx, output, &ofraglen, max_output_len,
926 pbuf, pcount);
927 if (rv != SECSuccess)
928 return rv;
929
930 /*
931 * For now anyway, all of our ciphers have the same number of
932 * bytes of output as they do input. If this ever becomes untrue,
933 * then SecCmsCipherContextDecryptLength needs to be made smarter!
934 */
935 PORT_Assert(ofraglen == pcount);
936
937 /*
938 * Account for the bytes now in output.
939 */
940 max_output_len -= ofraglen;
941 output_len += ofraglen;
942 output += ofraglen;
943 }
944
945 /*
946 * If this is our last call, we expect to have an exact number of
947 * blocks left to be decrypted; we will decrypt them all.
948 *
949 * If not our last call, we always save between 1 and bsize bytes
950 * until next time. (We must do this because we cannot be sure
951 * that none of the decrypted bytes are padding bytes until we
952 * have at least another whole block of data. You cannot tell by
953 * looking -- the data could be anything -- you can only tell by
954 * context, knowing you are looking at the last block.) We could
955 * decrypt a whole block now but it is easier if we just treat it
956 * the same way we treat partial block bytes.
957 */
958 if (final) {
959 if (padsize) {
960 blocks = input_len / padsize;
961 ifraglen = blocks * padsize;
962 } else ifraglen = input_len;
963 PORT_Assert (ifraglen == input_len);
964
965 if (ifraglen != input_len) {
966 PORT_SetError(SEC_ERROR_BAD_DATA);
967 return SECFailure;
968 }
969 } else {
970 blocks = (input_len - 1) / bsize;
971 ifraglen = blocks * bsize;
972 PORT_Assert (ifraglen < input_len);
973
974 pcount = input_len - ifraglen;
975 PORT_Memcpy (pbuf, input + ifraglen, pcount);
976 cc->pending_count = pcount;
977 }
978
979 if (ifraglen) {
980 rv = (* cc->doit)(cc->cx, output, &ofraglen, max_output_len,
981 input, ifraglen);
982 if (rv != SECSuccess)
983 return rv;
984
985 /*
986 * For now anyway, all of our ciphers have the same number of
987 * bytes of output as they do input. If this ever becomes untrue,
988 * then sec_PKCS7DecryptLength needs to be made smarter!
989 */
990 PORT_Assert (ifraglen == ofraglen);
991 if (ifraglen != ofraglen) {
992 PORT_SetError(SEC_ERROR_BAD_DATA);
993 return SECFailure;
994 }
995
996 output_len += ofraglen;
997 } else {
998 ofraglen = 0;
999 }
1000
1001 /*
1002 * If we just did our very last block, "remove" the padding by
1003 * adjusting the output length.
1004 */
1005 if (final && (padsize != 0)) {
1006 unsigned int padlen = *(output + ofraglen - 1);
1007
1008 if (padlen == 0 || padlen > padsize) {
1009 PORT_SetError(SEC_ERROR_BAD_DATA);
1010 return SECFailure;
1011 }
1012 output_len -= padlen;
1013 }
1014
1015 PORT_Assert (output_len_p != NULL || output_len == 0);
1016 if (output_len_p != NULL)
1017 *output_len_p = output_len;
1018
1019 return SECSuccess;
1020 #endif
1021 }
1022
1023 /*
1024 * SecCmsCipherContextEncrypt - do the encryption
1025 *
1026 * cc - the cipher context
1027 * output - buffer for decrypted result bytes
1028 * output_len_p - number of bytes in output
1029 * max_output_len - upper bound on bytes to put into output
1030 * input - pointer to input bytes
1031 * input_len - number of input bytes
1032 * final - true if this is the final chunk of data
1033 *
1034 * Encrypts a given length of input buffer (starting at "input" and
1035 * containing "input_len" bytes), placing the encrypted bytes in
1036 * "output" and storing the output length in "*output_len_p".
1037 * "cc" is the return value from SecCmsCipherStartEncrypt.
1038 * When "final" is true, this is the last of the data to be encrypted.
1039 *
1040 * This is much more complicated than it sounds when the cipher is
1041 * a block-type, meaning that the encryption function will only
1042 * operate on whole blocks. But our caller is operating stream-wise,
1043 * and can pass in any number of bytes. So we need to keep track
1044 * of block boundaries. We save excess bytes between calls in "cc".
1045 * We also need to add padding bytes at the end. PKCS #7 specifies
1046 * that the padding used for a block cipher is a string of bytes,
1047 * each of whose value is the same as the length of the padding,
1048 * and that all data is padded. (Even data that starts out with
1049 * an exact multiple of blocks gets added to it another block,
1050 * all of which is padding.)
1051 *
1052 * XXX I would kind of like to combine this with the function above
1053 * which does decryption, since they have a lot in common. But the
1054 * tricky parts about padding and filling blocks would be much
1055 * harder to read that way, so I left them separate. At least for
1056 * now until it is clear that they are right.
1057 */
1058 OSStatus
1059 SecCmsCipherContextEncrypt(SecCmsCipherContextRef cc, unsigned char *output,
1060 size_t *output_len_p, size_t max_output_len,
1061 const unsigned char *input, size_t input_len,
1062 Boolean final)
1063 {
1064 #if 1
1065 return SecCmsCipherContextCrypt(cc, output,
1066 output_len_p, max_output_len,
1067 input, input_len,
1068 final, PR_TRUE);
1069 #else
1070 int blocks, bsize, padlen, pcount, padsize;
1071 unsigned int max_needed, ifraglen, ofraglen, output_len;
1072 unsigned char *pbuf;
1073 OSStatus rv;
1074
1075 PORT_Assert (cc->encrypt);
1076
1077 /*
1078 * Check that we have enough room for the output. Our caller should
1079 * already handle this; failure is really an internal error (i.e. bug).
1080 */
1081 max_needed = SecCmsCipherContextEncryptLength (cc, input_len, final);
1082 PORT_Assert (max_output_len >= max_needed);
1083 if (max_output_len < max_needed) {
1084 /* PORT_SetError (XXX); */
1085 return SECFailure;
1086 }
1087
1088 bsize = cc->block_size;
1089 padsize = cc->pad_size;
1090
1091 /*
1092 * When no blocking and padding work to do, we can simply call the
1093 * cipher function and we are done.
1094 */
1095 if (bsize == 0) {
1096 return (*cc->doit)(cc->cx, output, output_len_p, max_output_len,
1097 input, input_len);
1098 }
1099
1100 pcount = cc->pending_count;
1101 pbuf = cc->pending_buf;
1102
1103 output_len = 0;
1104
1105 if (pcount) {
1106 /*
1107 * Try to fill in an entire block, starting with the bytes
1108 * we already have saved away.
1109 */
1110 while (input_len && pcount < bsize) {
1111 pbuf[pcount++] = *input++;
1112 input_len--;
1113 }
1114 /*
1115 * If we do not have a full block and we know we will be
1116 * called again, then we are done for now.
1117 */
1118 if (pcount < bsize && !final) {
1119 cc->pending_count = pcount;
1120 if (output_len_p != NULL)
1121 *output_len_p = 0;
1122 return SECSuccess;
1123 }
1124 /*
1125 * If we have a whole block available, encrypt it.
1126 */
1127 if ((padsize == 0) || (pcount % padsize) == 0) {
1128 rv = (* cc->doit) (cc->cx, output, &ofraglen, max_output_len,
1129 pbuf, pcount);
1130 if (rv != SECSuccess)
1131 return rv;
1132
1133 /*
1134 * For now anyway, all of our ciphers have the same number of
1135 * bytes of output as they do input. If this ever becomes untrue,
1136 * then sec_PKCS7EncryptLength needs to be made smarter!
1137 */
1138 PORT_Assert (ofraglen == pcount);
1139
1140 /*
1141 * Account for the bytes now in output.
1142 */
1143 max_output_len -= ofraglen;
1144 output_len += ofraglen;
1145 output += ofraglen;
1146
1147 pcount = 0;
1148 }
1149 }
1150
1151 if (input_len) {
1152 PORT_Assert (pcount == 0);
1153
1154 blocks = input_len / bsize;
1155 ifraglen = blocks * bsize;
1156
1157 if (ifraglen) {
1158 rv = (* cc->doit) (cc->cx, output, &ofraglen, max_output_len,
1159 input, ifraglen);
1160 if (rv != SECSuccess)
1161 return rv;
1162
1163 /*
1164 * For now anyway, all of our ciphers have the same number of
1165 * bytes of output as they do input. If this ever becomes untrue,
1166 * then sec_PKCS7EncryptLength needs to be made smarter!
1167 */
1168 PORT_Assert (ifraglen == ofraglen);
1169
1170 max_output_len -= ofraglen;
1171 output_len += ofraglen;
1172 output += ofraglen;
1173 }
1174
1175 pcount = input_len - ifraglen;
1176 PORT_Assert (pcount < bsize);
1177 if (pcount)
1178 PORT_Memcpy (pbuf, input + ifraglen, pcount);
1179 }
1180
1181 if (final) {
1182 padlen = padsize - (pcount % padsize);
1183 PORT_Memset (pbuf + pcount, padlen, padlen);
1184 rv = (* cc->doit) (cc->cx, output, &ofraglen, max_output_len,
1185 pbuf, pcount+padlen);
1186 if (rv != SECSuccess)
1187 return rv;
1188
1189 /*
1190 * For now anyway, all of our ciphers have the same number of
1191 * bytes of output as they do input. If this ever becomes untrue,
1192 * then sec_PKCS7EncryptLength needs to be made smarter!
1193 */
1194 PORT_Assert (ofraglen == (pcount+padlen));
1195 output_len += ofraglen;
1196 } else {
1197 cc->pending_count = pcount;
1198 }
1199
1200 PORT_Assert (output_len_p != NULL || output_len == 0);
1201 if (output_len_p != NULL)
1202 *output_len_p = output_len;
1203
1204 return SECSuccess;
1205 #endif
1206 }