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