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