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