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