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