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/ 
   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. 
  12  * The Original Code is the Netscape security libraries. 
  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 
  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 
  35  * Encryption/decryption routines for CMS implementation, none of which are exported. 
  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> 
  50  * ------------------------------------------------------------------- 
  55 typedef OSStatus (*nss_cms_cipher_function
) (void *, unsigned char *, unsigned int *, 
  56                                         unsigned int, const unsigned char *, unsigned int); 
  57 typedef OSStatus (*nss_cms_cipher_destroy
) (void *, Boolean
); 
  60 #define BLOCK_SIZE 4096 
  62 struct SecCmsCipherContextStr 
{ 
  64     CSSM_CC_HANDLE      cc
;                     /* CSP CONTEXT */ 
  65     Boolean             encrypt
;                /* encrypt / decrypt switch */ 
  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 */ 
  73     int                 pending_count
;          /* pending data (not yet en/decrypted */ 
  74     unsigned char       pending_buf
[BLOCK_SIZE
];/* because of blocking */ 
  78 typedef struct sec_rc2cbcParameterStr 
{ 
  79     SECItem rc2ParameterVersion
; 
  81 } sec_rc2cbcParameter
; 
  83 static const SecAsn1Template sec_rc2cbc_parameter_template
[] = { 
  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
) }, 
  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. 
  98 DER_GetInteger(SECItem 
*it
) 
 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
; 
 108     ofloinit 
= ival 
& overflow
; 
 111         if ((ival 
& overflow
) != ofloinit
) { 
 112             PORT_SetError(SEC_ERROR_BAD_DER
); 
 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:) */ 
 128 static unsigned char  rc2_map(SECItem 
*version
) 
 132     x 
= DER_GetInteger(version
); 
 142 static unsigned long  rc2_unmap(unsigned long x
) 
 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 
 159 static SecCmsCipherContextRef
 
 160 SecCmsCipherContextStart(PRArenaPool 
*poolp
, SecSymmetricKeyRef key
, SECAlgorithmID 
*algid
, Boolean encrypt
) 
 162     SecCmsCipherContextRef cc
; 
 163     CSSM_CC_HANDLE ciphercc 
= 0; 
 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
; 
 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) }; 
 176     rv 
= SecKeyGetCSPHandle(key
, &cspHandle
); 
 179     rv 
= SecKeyGetCSSMKey(key
, &cssmKey
); 
 183     // @@@ Add support for PBE based stuff 
 185     oidData 
= SECOID_FindOID(&algid
->algorithm
); 
 188     algtag 
= oidData
->offset
; 
 189     algorithm 
= oidData
->cssmAlgorithm
; 
 195     case SEC_OID_RC2_CBC
: 
 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
; 
 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
; 
 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
; 
 220     case SEC_OID_DES_OFB
: 
 221         mode 
= CSSM_ALGMODE_OFBPadIV8
; 
 224     case SEC_OID_DES_CFB
: 
 225         mode 
= CSSM_ALGMODE_CFBPadIV8
; 
 234         CSSM_CC_HANDLE randomcc
; 
 235         //SECItem *parameters; 
 237         // Generate random initVector 
 238         if (CSSM_CSP_CreateRandomGenContext(cspHandle
, 
 239                 CSSM_ALGID_APPLE_YARROW
, 
 245         if (CSSM_GenerateRandom(randomcc
, &initVector
)) 
 247         CSSM_DeleteContext(randomcc
); 
 249         // Put IV into algid.parameters 
 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
)) 
 272         case SEC_OID_RC2_CBC
: 
 274             sec_rc2cbcParameter rc2 
= {}; 
 275             unsigned long rc2version
; 
 279             rc2version 
= rc2_unmap(cssmKey
->KeyHeader
.LogicalKeySizeInBits
); 
 280             if (!SEC_ASN1EncodeUnsignedInteger (NULL
, &(rc2
.rc2ParameterVersion
), 
 283             newParams 
= SEC_ASN1EncodeItem (poolp
, &algid
->parameters
, &rc2
, 
 284                                 sec_rc2cbc_parameter_template
); 
 285             PORT_Free(rc2
.rc2ParameterVersion
.Data
); 
 286             rc2
.rc2ParameterVersion
.Data 
= NULL
; 
 287             if (newParams 
== NULL
) 
 291         case SEC_OID_RC5_CBC_PAD
: 
 293             // @@@ Implement rc5 params stuff. 
 300         // Extract IV from algid.parameters 
 301         // Put IV into algid.parameters 
 305         case SEC_OID_DES_EDE3_CBC
: 
 306         case SEC_OID_DES_EDE
: 
 307         case SEC_OID_DES_CBC
: 
 308         case SEC_OID_AES_128_CBC
: 
 309         case SEC_OID_AES_192_CBC
: 
 310         case SEC_OID_AES_256_CBC
: 
 311         case SEC_OID_FORTEZZA_SKIPJACK
: 
 312         case SEC_OID_DES_ECB
: 
 313         case SEC_OID_AES_128_ECB
: 
 314         case SEC_OID_AES_192_ECB
: 
 315         case SEC_OID_AES_256_ECB
: 
 316         case SEC_OID_DES_OFB
: 
 317         case SEC_OID_DES_CFB
: 
 320             /* Just decode the initVector from an octet string. */ 
 321             rv 
= SEC_ASN1DecodeItem(NULL
, &iv
, kSecAsn1OctetStringTemplate
, &(algid
->parameters
)); 
 324             if (initVector
.Length 
!= iv
.Length
) { 
 329             memcpy(initVector
.Data
, iv
.Data
, initVector
.Length
); 
 334         case SEC_OID_RC2_CBC
: 
 336             sec_rc2cbcParameter rc2 
= {}; 
 337             unsigned long ulEffectiveBits
; 
 339             rv 
= SEC_ASN1DecodeItem(NULL
, &rc2 
,sec_rc2cbc_parameter_template
, 
 340                                                             &(algid
->parameters
)); 
 344             if (initVector
.Length 
!= rc2
.iv
.Length
) { 
 345                 PORT_Free(rc2
.iv
.Data
); 
 347                 PORT_Free(rc2
.rc2ParameterVersion
.Data
); 
 348                 rc2
.rc2ParameterVersion
.Data 
= NULL
; 
 351             memcpy(initVector
.Data
, rc2
.iv
.Data
, initVector
.Length
); 
 352             PORT_Free(rc2
.iv
.Data
); 
 355             ulEffectiveBits 
= rc2_map(&rc2
.rc2ParameterVersion
); 
 356             PORT_Free(rc2
.rc2ParameterVersion
.Data
); 
 357             rc2
.rc2ParameterVersion
.Data 
= NULL
; 
 358             if (ulEffectiveBits 
!= cssmKey
->KeyHeader
.LogicalKeySizeInBits
) 
 362         case SEC_OID_RC5_CBC_PAD
: 
 364             // @@@ Implement rc5 params stuff. 
 370     if (CSSM_CSP_CreateSymmetricContext(cspHandle
, 
 373             NULL
, /* accessCred */ 
 382         rv 
= CSSM_EncryptDataInit(ciphercc
); 
 384         rv 
= CSSM_DecryptDataInit(ciphercc
); 
 388     cc 
= (SecCmsCipherContextRef
)PORT_ZAlloc(sizeof(SecCmsCipherContext
)); 
 393     cc
->encrypt 
= encrypt
; 
 398         CSSM_DeleteContext(ciphercc
); 
 404  * SecCmsCipherContextStartDecrypt - create a cipher context to do decryption 
 405  * based on the given bulk * encryption key and algorithm identifier (which may include an iv). 
 407  * XXX Once both are working, it might be nice to combine this and the 
 408  * function below (for starting up encryption) into one routine, and just 
 409  * have two simple cover functions which call it.  
 411 SecCmsCipherContextRef
 
 412 SecCmsCipherContextStartDecrypt(SecSymmetricKeyRef key
, SECAlgorithmID 
*algid
) 
 414     return SecCmsCipherContextStart(NULL
, key
, algid
, PR_FALSE
); 
 416     SecCmsCipherContextRef cc
; 
 418     CK_MECHANISM_TYPE mechanism
; 
 423     algtag 
= SECOID_GetAlgorithmTag(algid
); 
 425     /* set param and mechanism */ 
 426     if (SEC_PKCS5IsAlgorithmPBEAlg(algid
)) { 
 427         CK_MECHANISM pbeMech
, cryptoMech
; 
 428         CSSM_DATA_PTR pbeParams
; 
 429         SEC_PKCS5KeyAndPassword 
*keyPwd
; 
 431         PORT_Memset(&pbeMech
, 0, sizeof(CK_MECHANISM
)); 
 432         PORT_Memset(&cryptoMech
, 0, sizeof(CK_MECHANISM
)); 
 435          * in this case, key is not actually a SecSymmetricKeyRef, but a SEC_PKCS5KeyAndPassword * 
 437         keyPwd 
= (SEC_PKCS5KeyAndPassword 
*)key
; 
 440         /* find correct PK11 mechanism and parameters to initialize pbeMech */ 
 441         pbeMech
.mechanism 
= PK11_AlgtagToMechanism(algtag
); 
 442         pbeParams 
= PK11_ParamFromAlgid(algid
); 
 445         pbeMech
.pParameter 
= pbeParams
->Data
; 
 446         pbeMech
.ulParameterLen 
= pbeParams
->Length
; 
 448         /* now map pbeMech to cryptoMech */ 
 449         if (PK11_MapPBEMechanismToCryptoMechanism(&pbeMech
, &cryptoMech
, keyPwd
->pwitem
, 
 450                                                   PR_FALSE
) != CKR_OK
) {  
 451             SECITEM_ZfreeItem(pbeParams
, PR_TRUE
); 
 454         SECITEM_ZfreeItem(pbeParams
, PR_TRUE
); 
 456         /* and use it to initialize param & mechanism */ 
 457         if ((param 
= (CSSM_DATA_PTR
)PORT_ZAlloc(sizeof(CSSM_DATA
))) == NULL
) 
 460         param
->Data 
= (unsigned char *)cryptoMech
.pParameter
; 
 461         param
->Length 
= cryptoMech
.ulParameterLen
; 
 462         mechanism 
= cryptoMech
.mechanism
; 
 464         mechanism 
= PK11_AlgtagToMechanism(algtag
); 
 465         if ((param 
= PK11_ParamFromAlgid(algid
)) == NULL
) 
 469     cc 
= (SecCmsCipherContextRef
)PORT_ZAlloc(sizeof(SecCmsCipherContext
)); 
 471         SECITEM_FreeItem(param
,PR_TRUE
); 
 475     /* figure out pad and block sizes */ 
 476     cc
->pad_size 
= PK11_GetBlockSize(mechanism
, param
); 
 477     slot 
= PK11_GetSlotFromKey(key
); 
 478     cc
->block_size 
= PK11_IsHW(slot
) ? BLOCK_SIZE 
: cc
->pad_size
; 
 481     /* create PK11 cipher context */ 
 482     ciphercx 
= PK11_CreateContextBySymKey(mechanism
, CKA_DECRYPT
, key
, param
); 
 483     SECITEM_FreeItem(param
, PR_TRUE
); 
 484     if (ciphercx 
== NULL
) { 
 490     cc
->doit 
=  (nss_cms_cipher_function
) PK11_CipherOp
; 
 491     cc
->destroy 
= (nss_cms_cipher_destroy
) PK11_DestroyContext
; 
 492     cc
->encrypt 
= PR_FALSE
; 
 493     cc
->pending_count 
= 0; 
 500  * SecCmsCipherContextStartEncrypt - create a cipher object to do encryption, 
 501  * based on the given bulk encryption key and algorithm tag.  Fill in the algorithm 
 502  * identifier (which may include an iv) appropriately. 
 504  * XXX Once both are working, it might be nice to combine this and the 
 505  * function above (for starting up decryption) into one routine, and just 
 506  * have two simple cover functions which call it.  
 508 SecCmsCipherContextRef
 
 509 SecCmsCipherContextStartEncrypt(PRArenaPool 
*poolp
, SecSymmetricKeyRef key
, SECAlgorithmID 
*algid
) 
 511     return SecCmsCipherContextStart(poolp
, key
, algid
, PR_TRUE
); 
 513     SecCmsCipherContextRef cc
; 
 517     CK_MECHANISM_TYPE mechanism
; 
 519     Boolean needToEncodeAlgid 
= PR_FALSE
; 
 520     SECOidTag algtag 
= SECOID_GetAlgorithmTag(algid
); 
 522     /* set param and mechanism */ 
 523     if (SEC_PKCS5IsAlgorithmPBEAlg(algid
)) { 
 524         CK_MECHANISM pbeMech
, cryptoMech
; 
 525         CSSM_DATA_PTR pbeParams
; 
 526         SEC_PKCS5KeyAndPassword 
*keyPwd
; 
 528         PORT_Memset(&pbeMech
, 0, sizeof(CK_MECHANISM
)); 
 529         PORT_Memset(&cryptoMech
, 0, sizeof(CK_MECHANISM
)); 
 532          * in this case, key is not actually a SecSymmetricKeyRef, but a SEC_PKCS5KeyAndPassword * 
 534         keyPwd 
= (SEC_PKCS5KeyAndPassword 
*)key
; 
 537         /* find correct PK11 mechanism and parameters to initialize pbeMech */ 
 538         pbeMech
.mechanism 
= PK11_AlgtagToMechanism(algtag
); 
 539         pbeParams 
= PK11_ParamFromAlgid(algid
); 
 542         pbeMech
.pParameter 
= pbeParams
->Data
; 
 543         pbeMech
.ulParameterLen 
= pbeParams
->Length
; 
 545         /* now map pbeMech to cryptoMech */ 
 546         if (PK11_MapPBEMechanismToCryptoMechanism(&pbeMech
, &cryptoMech
, keyPwd
->pwitem
, 
 547                                                   PR_FALSE
) != CKR_OK
) {  
 548             SECITEM_ZfreeItem(pbeParams
, PR_TRUE
); 
 551         SECITEM_ZfreeItem(pbeParams
, PR_TRUE
); 
 553         /* and use it to initialize param & mechanism */ 
 554         if ((param 
= (CSSM_DATA_PTR
)PORT_ZAlloc(sizeof(CSSM_DATA
))) == NULL
) 
 557         param
->Data 
= (unsigned char *)cryptoMech
.pParameter
; 
 558         param
->Length 
= cryptoMech
.ulParameterLen
; 
 559         mechanism 
= cryptoMech
.mechanism
; 
 561         mechanism 
= PK11_AlgtagToMechanism(algtag
); 
 562         if ((param 
= PK11_GenerateNewParam(mechanism
, key
)) == NULL
) 
 564         needToEncodeAlgid 
= PR_TRUE
; 
 567     cc 
= (SecCmsCipherContextRef
)PORT_ZAlloc(sizeof(SecCmsCipherContext
)); 
 571     /* now find pad and block sizes for our mechanism */ 
 572     cc
->pad_size 
= PK11_GetBlockSize(mechanism
,param
); 
 573     slot 
= PK11_GetSlotFromKey(key
); 
 574     cc
->block_size 
= PK11_IsHW(slot
) ? BLOCK_SIZE 
: cc
->pad_size
; 
 577     /* and here we go, creating a PK11 cipher context */ 
 578     ciphercx 
= PK11_CreateContextBySymKey(mechanism
, CKA_ENCRYPT
, key
, param
); 
 579     if (ciphercx 
== NULL
) { 
 586      * These are placed after the CreateContextBySymKey() because some 
 587      * mechanisms have to generate their IVs from their card (i.e. FORTEZZA). 
 588      * Don't move it from here. 
 589      * XXX is that right? the purpose of this is to get the correct algid 
 590      *     containing the IVs etc. for encoding. this means we need to set this up 
 591      *     BEFORE encoding the algid in the contentInfo, right? 
 593     if (needToEncodeAlgid
) { 
 594         rv 
= PK11_ParamToAlgid(algtag
, param
, poolp
, algid
); 
 595         if(rv 
!= SECSuccess
) { 
 603     cc
->doit 
= (nss_cms_cipher_function
)PK11_CipherOp
; 
 604     cc
->destroy 
= (nss_cms_cipher_destroy
)PK11_DestroyContext
; 
 605     cc
->encrypt 
= PR_TRUE
; 
 606     cc
->pending_count 
= 0; 
 609     SECITEM_FreeItem(param
, PR_TRUE
); 
 616 SecCmsCipherContextDestroy(SecCmsCipherContextRef cc
) 
 618     PORT_Assert(cc 
!= NULL
); 
 621     CSSM_DeleteContext(cc
->cc
); 
 626 SecCmsCipherContextLength(SecCmsCipherContextRef cc
, unsigned int input_len
, Boolean final
, Boolean encrypt
) 
 628     CSSM_QUERY_SIZE_DATA dataBlockSize
[2] = { { input_len
, 0 }, { input_len
, 0 } }; 
 629     /* 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. */ 
 630     OSStatus rv 
= CSSM_QuerySize(cc
->cc
, cc
->encrypt
, final 
? 1 : 2, dataBlockSize
); 
 637     return dataBlockSize
[0].SizeOutputBlock
; 
 641  * SecCmsCipherContextDecryptLength - find the output length of the next call to decrypt. 
 643  * cc - the cipher context 
 644  * input_len - number of bytes used as input 
 645  * final - true if this is the final chunk of data 
 647  * Result can be used to perform memory allocations.  Note that the amount 
 648  * is exactly accurate only when not doing a block cipher or when final 
 649  * is false, otherwise it is an upper bound on the amount because until 
 650  * we see the data we do not know how many padding bytes there are 
 651  * (always between 1 and bsize). 
 653  * Note that this can return zero, which does not mean that the decrypt 
 654  * operation can be skipped!  (It simply means that there are not enough 
 655  * bytes to make up an entire block; the bytes will be reserved until 
 656  * there are enough to encrypt/decrypt at least one block.)  However, 
 657  * if zero is returned it *does* mean that no output buffer need be 
 658  * passed in to the subsequent decrypt operation, as no output bytes 
 662 SecCmsCipherContextDecryptLength(SecCmsCipherContextRef cc
, size_t input_len
, Boolean final
) 
 665     return SecCmsCipherContextLength(cc
, (unsigned int)input_len
, final
, PR_FALSE
); 
 667     int blocks
, block_size
; 
 669     PORT_Assert (! cc
->encrypt
); 
 671     block_size 
= cc
->block_size
; 
 674      * If this is not a block cipher, then we always have the same 
 675      * number of output bytes as we had input bytes. 
 681      * On the final call, we will always use up all of the pending 
 682      * bytes plus all of the input bytes, *but*, there will be padding 
 683      * at the end and we cannot predict how many bytes of padding we 
 684      * will end up removing.  The amount given here is actually known 
 685      * to be at least 1 byte too long (because we know we will have 
 686      * at least 1 byte of padding), but seemed clearer/better to me. 
 689         return cc
->pending_count 
+ input_len
; 
 692      * Okay, this amount is exactly what we will output on the 
 693      * next cipher operation.  We will always hang onto the last 
 694      * 1 - block_size bytes for non-final operations.  That is, 
 695      * we will do as many complete blocks as we can *except* the 
 696      * last block (complete or partial).  (This is because until 
 697      * we know we are at the end, we cannot know when to interpret 
 698      * and removing the padding byte(s), which are guaranteed to 
 701     blocks 
= (cc
->pending_count 
+ input_len 
- 1) / block_size
; 
 702     return blocks 
* block_size
; 
 707  * SecCmsCipherContextEncryptLength - find the output length of the next call to encrypt. 
 709  * cc - the cipher context 
 710  * input_len - number of bytes used as input 
 711  * final - true if this is the final chunk of data 
 713  * Result can be used to perform memory allocations. 
 715  * Note that this can return zero, which does not mean that the encrypt 
 716  * operation can be skipped!  (It simply means that there are not enough 
 717  * bytes to make up an entire block; the bytes will be reserved until 
 718  * there are enough to encrypt/decrypt at least one block.)  However, 
 719  * if zero is returned it *does* mean that no output buffer need be 
 720  * passed in to the subsequent encrypt operation, as no output bytes 
 724 SecCmsCipherContextEncryptLength(SecCmsCipherContextRef cc
, size_t input_len
, Boolean final
) 
 727     return SecCmsCipherContextLength(cc
, (unsigned int)input_len
, final
, PR_TRUE
); 
 729     int blocks
, block_size
; 
 732     PORT_Assert (cc
->encrypt
); 
 734     block_size 
= cc
->block_size
; 
 735     pad_size 
= cc
->pad_size
; 
 738      * If this is not a block cipher, then we always have the same 
 739      * number of output bytes as we had input bytes. 
 745      * On the final call, we only send out what we need for 
 746      * remaining bytes plus the padding.  (There is always padding, 
 747      * so even if we have an exact number of blocks as input, we 
 748      * will add another full block that is just padding.) 
 752             return cc
->pending_count 
+ input_len
; 
 754             blocks 
= (cc
->pending_count 
+ input_len
) / pad_size
; 
 756             return blocks
*pad_size
; 
 761      * Now, count the number of complete blocks of data we have. 
 763     blocks 
= (cc
->pending_count 
+ input_len
) / block_size
; 
 766     return blocks 
* block_size
; 
 772 SecCmsCipherContextCrypt(SecCmsCipherContextRef cc
, unsigned char *output
, 
 773                   size_t *output_len_p
, size_t max_output_len
, 
 774                   const unsigned char *input
, size_t input_len
, 
 775                   Boolean final
, Boolean encrypt
) 
 777     CSSM_DATA outputBuf 
= { max_output_len
, output 
}; 
 778     CSSM_SIZE bytes_output 
= 0; 
 783         CSSM_DATA inputBuf 
= { input_len
, (uint8 
*)input 
}; 
 786             rv 
= CSSM_EncryptDataUpdate(cc
->cc
, &inputBuf
, 1, &outputBuf
, 1, &bytes_output
); 
 788             rv 
= CSSM_DecryptDataUpdate(cc
->cc
, &inputBuf
, 1, &outputBuf
, 1, &bytes_output
); 
 793         CSSM_DATA remainderBuf 
= { max_output_len 
- bytes_output
, output 
+ bytes_output 
}; 
 795             rv 
= CSSM_EncryptDataFinal(cc
->cc
, &remainderBuf
); 
 797             rv 
= CSSM_DecryptDataFinal(cc
->cc
, &remainderBuf
); 
 799         bytes_output 
+= remainderBuf
.Length
; 
 803         PORT_SetError(SEC_ERROR_BAD_DATA
); 
 804     else if (output_len_p
) 
 805         *output_len_p 
= bytes_output
; 
 811  * SecCmsCipherContextDecrypt - do the decryption 
 813  * cc - the cipher context 
 814  * output - buffer for decrypted result bytes 
 815  * output_len_p - number of bytes in output 
 816  * max_output_len - upper bound on bytes to put into output 
 817  * input - pointer to input bytes 
 818  * input_len - number of input bytes 
 819  * final - true if this is the final chunk of data 
 821  * Decrypts a given length of input buffer (starting at "input" and 
 822  * containing "input_len" bytes), placing the decrypted bytes in 
 823  * "output" and storing the output length in "*output_len_p". 
 824  * "cc" is the return value from SecCmsCipherStartDecrypt. 
 825  * When "final" is true, this is the last of the data to be decrypted. 
 827  * This is much more complicated than it sounds when the cipher is 
 828  * a block-type, meaning that the decryption function will only 
 829  * operate on whole blocks.  But our caller is operating stream-wise, 
 830  * and can pass in any number of bytes.  So we need to keep track 
 831  * of block boundaries.  We save excess bytes between calls in "cc". 
 832  * We also need to determine which bytes are padding, and remove 
 833  * them from the output.  We can only do this step when we know we 
 834  * have the final block of data.  PKCS #7 specifies that the padding 
 835  * used for a block cipher is a string of bytes, each of whose value is 
 836  * the same as the length of the padding, and that all data is padded. 
 837  * (Even data that starts out with an exact multiple of blocks gets 
 838  * added to it another block, all of which is padding.) 
 841 SecCmsCipherContextDecrypt(SecCmsCipherContextRef cc
, unsigned char *output
, 
 842                   size_t *output_len_p
, size_t max_output_len
, 
 843                   const unsigned char *input
, size_t input_len
, 
 847     return SecCmsCipherContextCrypt(cc
, output
, 
 848                   output_len_p
,  max_output_len
, 
 852     int blocks
, bsize
, pcount
, padsize
; 
 853     unsigned int max_needed
, ifraglen
, ofraglen
, output_len
; 
 857     PORT_Assert (! cc
->encrypt
); 
 860      * Check that we have enough room for the output.  Our caller should 
 861      * already handle this; failure is really an internal error (i.e. bug). 
 863     max_needed 
= SecCmsCipherContextDecryptLength(cc
, input_len
, final
); 
 864     PORT_Assert (max_output_len 
>= max_needed
); 
 865     if (max_output_len 
< max_needed
) { 
 866         /* PORT_SetError (XXX); */ 
 871      * hardware encryption does not like small decryption sizes here, so we 
 872      * allow both blocking and padding. 
 874     bsize 
= cc
->block_size
; 
 875     padsize 
= cc
->pad_size
; 
 878      * When no blocking or padding work to do, we can simply call the 
 879      * cipher function and we are done. 
 882         return (* cc
->doit
) (cc
->cx
, output
, output_len_p
, max_output_len
, 
 886     pcount 
= cc
->pending_count
; 
 887     pbuf 
= cc
->pending_buf
; 
 893          * Try to fill in an entire block, starting with the bytes 
 894          * we already have saved away. 
 896         while (input_len 
&& pcount 
< bsize
) { 
 897             pbuf
[pcount
++] = *input
++; 
 901          * If we have at most a whole block and this is not our last call, 
 902          * then we are done for now.  (We do not try to decrypt a lone 
 903          * single block because we cannot interpret the padding bytes 
 904          * until we know we are handling the very last block of all input.) 
 906         if (input_len 
== 0 && !final
) { 
 907             cc
->pending_count 
= pcount
; 
 913          * Given the logic above, we expect to have a full block by now. 
 914          * If we do not, there is something wrong, either with our own 
 915          * logic or with (length of) the data given to us. 
 917         if ((padsize 
!= 0) && (pcount 
% padsize
) != 0) { 
 919             PORT_SetError (SEC_ERROR_BAD_DATA
); 
 925         rv 
= (*cc
->doit
)(cc
->cx
, output
, &ofraglen
, max_output_len
, 
 927         if (rv 
!= SECSuccess
) 
 931          * For now anyway, all of our ciphers have the same number of 
 932          * bytes of output as they do input.  If this ever becomes untrue, 
 933          * then SecCmsCipherContextDecryptLength needs to be made smarter! 
 935         PORT_Assert(ofraglen 
== pcount
); 
 938          * Account for the bytes now in output. 
 940         max_output_len 
-= ofraglen
; 
 941         output_len 
+= ofraglen
; 
 946      * If this is our last call, we expect to have an exact number of 
 947      * blocks left to be decrypted; we will decrypt them all. 
 949      * If not our last call, we always save between 1 and bsize bytes 
 950      * until next time.  (We must do this because we cannot be sure 
 951      * that none of the decrypted bytes are padding bytes until we 
 952      * have at least another whole block of data.  You cannot tell by 
 953      * looking -- the data could be anything -- you can only tell by 
 954      * context, knowing you are looking at the last block.)  We could 
 955      * decrypt a whole block now but it is easier if we just treat it 
 956      * the same way we treat partial block bytes. 
 960             blocks 
= input_len 
/ padsize
; 
 961             ifraglen 
= blocks 
* padsize
; 
 962         } else ifraglen 
= input_len
; 
 963         PORT_Assert (ifraglen 
== input_len
); 
 965         if (ifraglen 
!= input_len
) { 
 966             PORT_SetError(SEC_ERROR_BAD_DATA
); 
 970         blocks 
= (input_len 
- 1) / bsize
; 
 971         ifraglen 
= blocks 
* bsize
; 
 972         PORT_Assert (ifraglen 
< input_len
); 
 974         pcount 
= input_len 
- ifraglen
; 
 975         PORT_Memcpy (pbuf
, input 
+ ifraglen
, pcount
); 
 976         cc
->pending_count 
= pcount
; 
 980         rv 
= (* cc
->doit
)(cc
->cx
, output
, &ofraglen
, max_output_len
, 
 982         if (rv 
!= SECSuccess
) 
 986          * For now anyway, all of our ciphers have the same number of 
 987          * bytes of output as they do input.  If this ever becomes untrue, 
 988          * then sec_PKCS7DecryptLength needs to be made smarter! 
 990         PORT_Assert (ifraglen 
== ofraglen
); 
 991         if (ifraglen 
!= ofraglen
) { 
 992             PORT_SetError(SEC_ERROR_BAD_DATA
); 
 996         output_len 
+= ofraglen
; 
1002      * If we just did our very last block, "remove" the padding by 
1003      * adjusting the output length. 
1005     if (final 
&& (padsize 
!= 0)) { 
1006         unsigned int padlen 
= *(output 
+ ofraglen 
- 1); 
1008         if (padlen 
== 0 || padlen 
> padsize
) { 
1009             PORT_SetError(SEC_ERROR_BAD_DATA
); 
1012         output_len 
-= padlen
; 
1015     PORT_Assert (output_len_p 
!= NULL 
|| output_len 
== 0); 
1016     if (output_len_p 
!= NULL
) 
1017         *output_len_p 
= output_len
; 
1024  * SecCmsCipherContextEncrypt - do the encryption 
1026  * cc - the cipher context 
1027  * output - buffer for decrypted result bytes 
1028  * output_len_p - number of bytes in output 
1029  * max_output_len - upper bound on bytes to put into output 
1030  * input - pointer to input bytes 
1031  * input_len - number of input bytes 
1032  * final - true if this is the final chunk of data 
1034  * Encrypts a given length of input buffer (starting at "input" and 
1035  * containing "input_len" bytes), placing the encrypted bytes in 
1036  * "output" and storing the output length in "*output_len_p". 
1037  * "cc" is the return value from SecCmsCipherStartEncrypt. 
1038  * When "final" is true, this is the last of the data to be encrypted. 
1040  * This is much more complicated than it sounds when the cipher is 
1041  * a block-type, meaning that the encryption function will only 
1042  * operate on whole blocks.  But our caller is operating stream-wise, 
1043  * and can pass in any number of bytes.  So we need to keep track 
1044  * of block boundaries.  We save excess bytes between calls in "cc". 
1045  * We also need to add padding bytes at the end.  PKCS #7 specifies 
1046  * that the padding used for a block cipher is a string of bytes, 
1047  * each of whose value is the same as the length of the padding, 
1048  * and that all data is padded.  (Even data that starts out with 
1049  * an exact multiple of blocks gets added to it another block, 
1050  * all of which is padding.) 
1052  * XXX I would kind of like to combine this with the function above 
1053  * which does decryption, since they have a lot in common.  But the 
1054  * tricky parts about padding and filling blocks would be much 
1055  * harder to read that way, so I left them separate.  At least for 
1056  * now until it is clear that they are right. 
1059 SecCmsCipherContextEncrypt(SecCmsCipherContextRef cc
, unsigned char *output
, 
1060                   size_t *output_len_p
, size_t max_output_len
, 
1061                   const unsigned char *input
, size_t input_len
, 
1065     return SecCmsCipherContextCrypt(cc
, output
, 
1066                   output_len_p
,  max_output_len
, 
1070     int blocks
, bsize
, padlen
, pcount
, padsize
; 
1071     unsigned int max_needed
, ifraglen
, ofraglen
, output_len
; 
1072     unsigned char *pbuf
; 
1075     PORT_Assert (cc
->encrypt
); 
1078      * Check that we have enough room for the output.  Our caller should 
1079      * already handle this; failure is really an internal error (i.e. bug). 
1081     max_needed 
= SecCmsCipherContextEncryptLength (cc
, input_len
, final
); 
1082     PORT_Assert (max_output_len 
>= max_needed
); 
1083     if (max_output_len 
< max_needed
) { 
1084         /* PORT_SetError (XXX); */ 
1088     bsize 
= cc
->block_size
; 
1089     padsize 
= cc
->pad_size
; 
1092      * When no blocking and padding work to do, we can simply call the 
1093      * cipher function and we are done. 
1096         return (*cc
->doit
)(cc
->cx
, output
, output_len_p
, max_output_len
, 
1100     pcount 
= cc
->pending_count
; 
1101     pbuf 
= cc
->pending_buf
; 
1107          * Try to fill in an entire block, starting with the bytes 
1108          * we already have saved away. 
1110         while (input_len 
&& pcount 
< bsize
) { 
1111             pbuf
[pcount
++] = *input
++; 
1115          * If we do not have a full block and we know we will be 
1116          * called again, then we are done for now. 
1118         if (pcount 
< bsize 
&& !final
) { 
1119             cc
->pending_count 
= pcount
; 
1120             if (output_len_p 
!= NULL
) 
1125          * If we have a whole block available, encrypt it. 
1127         if ((padsize 
== 0) || (pcount 
% padsize
) == 0) { 
1128             rv 
= (* cc
->doit
) (cc
->cx
, output
, &ofraglen
, max_output_len
, 
1130             if (rv 
!= SECSuccess
) 
1134              * For now anyway, all of our ciphers have the same number of 
1135              * bytes of output as they do input.  If this ever becomes untrue, 
1136              * then sec_PKCS7EncryptLength needs to be made smarter! 
1138             PORT_Assert (ofraglen 
== pcount
); 
1141              * Account for the bytes now in output. 
1143             max_output_len 
-= ofraglen
; 
1144             output_len 
+= ofraglen
; 
1152         PORT_Assert (pcount 
== 0); 
1154         blocks 
= input_len 
/ bsize
; 
1155         ifraglen 
= blocks 
* bsize
; 
1158             rv 
= (* cc
->doit
) (cc
->cx
, output
, &ofraglen
, max_output_len
, 
1160             if (rv 
!= SECSuccess
) 
1164              * For now anyway, all of our ciphers have the same number of 
1165              * bytes of output as they do input.  If this ever becomes untrue, 
1166              * then sec_PKCS7EncryptLength needs to be made smarter! 
1168             PORT_Assert (ifraglen 
== ofraglen
); 
1170             max_output_len 
-= ofraglen
; 
1171             output_len 
+= ofraglen
; 
1175         pcount 
= input_len 
- ifraglen
; 
1176         PORT_Assert (pcount 
< bsize
); 
1178             PORT_Memcpy (pbuf
, input 
+ ifraglen
, pcount
); 
1182         padlen 
= padsize 
- (pcount 
% padsize
); 
1183         PORT_Memset (pbuf 
+ pcount
, padlen
, padlen
); 
1184         rv 
= (* cc
->doit
) (cc
->cx
, output
, &ofraglen
, max_output_len
, 
1185                             pbuf
, pcount
+padlen
); 
1186         if (rv 
!= SECSuccess
) 
1190          * For now anyway, all of our ciphers have the same number of 
1191          * bytes of output as they do input.  If this ever becomes untrue, 
1192          * then sec_PKCS7EncryptLength needs to be made smarter! 
1194         PORT_Assert (ofraglen 
== (pcount
+padlen
)); 
1195         output_len 
+= ofraglen
; 
1197         cc
->pending_count 
= pcount
; 
1200     PORT_Assert (output_len_p 
!= NULL 
|| output_len 
== 0); 
1201     if (output_len_p 
!= NULL
) 
1202         *output_len_p 
= output_len
;