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             if (newParams 
== NULL
) 
 290         case SEC_OID_RC5_CBC_PAD
: 
 292             // @@@ Implement rc5 params stuff. 
 299         // Extract IV from algid.parameters 
 300         // Put IV into algid.parameters 
 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
: 
 319             /* Just decode the initVector from an octet string. */ 
 320             rv 
= SEC_ASN1DecodeItem(NULL
, &iv
, kSecAsn1OctetStringTemplate
, &(algid
->parameters
)); 
 323             if (initVector
.Length 
!= iv
.Length
) { 
 327             memcpy(initVector
.Data
, iv
.Data
, initVector
.Length
); 
 331         case SEC_OID_RC2_CBC
: 
 333             sec_rc2cbcParameter rc2 
= {}; 
 334             unsigned long ulEffectiveBits
; 
 336             rv 
= SEC_ASN1DecodeItem(NULL
, &rc2 
,sec_rc2cbc_parameter_template
, 
 337                                                             &(algid
->parameters
)); 
 341             if (initVector
.Length 
!= rc2
.iv
.Length
) { 
 342                 PORT_Free(rc2
.iv
.Data
); 
 343                 PORT_Free(rc2
.rc2ParameterVersion
.Data
); 
 346             memcpy(initVector
.Data
, rc2
.iv
.Data
, initVector
.Length
); 
 347             PORT_Free(rc2
.iv
.Data
); 
 349             ulEffectiveBits 
= rc2_map(&rc2
.rc2ParameterVersion
); 
 350             PORT_Free(rc2
.rc2ParameterVersion
.Data
); 
 351             if (ulEffectiveBits 
!= cssmKey
->KeyHeader
.LogicalKeySizeInBits
) 
 355         case SEC_OID_RC5_CBC_PAD
: 
 357             // @@@ Implement rc5 params stuff. 
 363     if (CSSM_CSP_CreateSymmetricContext(cspHandle
, 
 366             NULL
, /* accessCred */ 
 375         rv 
= CSSM_EncryptDataInit(ciphercc
); 
 377         rv 
= CSSM_DecryptDataInit(ciphercc
); 
 381     cc 
= (SecCmsCipherContextRef
)PORT_ZAlloc(sizeof(SecCmsCipherContext
)); 
 386     cc
->encrypt 
= encrypt
; 
 391         CSSM_DeleteContext(ciphercc
); 
 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). 
 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.  
 404 SecCmsCipherContextRef
 
 405 SecCmsCipherContextStartDecrypt(SecSymmetricKeyRef key
, SECAlgorithmID 
*algid
) 
 407     return SecCmsCipherContextStart(NULL
, key
, algid
, PR_FALSE
); 
 409     SecCmsCipherContextRef cc
; 
 411     CK_MECHANISM_TYPE mechanism
; 
 416     algtag 
= SECOID_GetAlgorithmTag(algid
); 
 418     /* set param and mechanism */ 
 419     if (SEC_PKCS5IsAlgorithmPBEAlg(algid
)) { 
 420         CK_MECHANISM pbeMech
, cryptoMech
; 
 421         CSSM_DATA_PTR pbeParams
; 
 422         SEC_PKCS5KeyAndPassword 
*keyPwd
; 
 424         PORT_Memset(&pbeMech
, 0, sizeof(CK_MECHANISM
)); 
 425         PORT_Memset(&cryptoMech
, 0, sizeof(CK_MECHANISM
)); 
 428          * in this case, key is not actually a SecSymmetricKeyRef, but a SEC_PKCS5KeyAndPassword * 
 430         keyPwd 
= (SEC_PKCS5KeyAndPassword 
*)key
; 
 433         /* find correct PK11 mechanism and parameters to initialize pbeMech */ 
 434         pbeMech
.mechanism 
= PK11_AlgtagToMechanism(algtag
); 
 435         pbeParams 
= PK11_ParamFromAlgid(algid
); 
 438         pbeMech
.pParameter 
= pbeParams
->Data
; 
 439         pbeMech
.ulParameterLen 
= pbeParams
->Length
; 
 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
); 
 447         SECITEM_ZfreeItem(pbeParams
, PR_TRUE
); 
 449         /* and use it to initialize param & mechanism */ 
 450         if ((param 
= (CSSM_DATA_PTR
)PORT_ZAlloc(sizeof(CSSM_DATA
))) == NULL
) 
 453         param
->Data 
= (unsigned char *)cryptoMech
.pParameter
; 
 454         param
->Length 
= cryptoMech
.ulParameterLen
; 
 455         mechanism 
= cryptoMech
.mechanism
; 
 457         mechanism 
= PK11_AlgtagToMechanism(algtag
); 
 458         if ((param 
= PK11_ParamFromAlgid(algid
)) == NULL
) 
 462     cc 
= (SecCmsCipherContextRef
)PORT_ZAlloc(sizeof(SecCmsCipherContext
)); 
 464         SECITEM_FreeItem(param
,PR_TRUE
); 
 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
; 
 474     /* create PK11 cipher context */ 
 475     ciphercx 
= PK11_CreateContextBySymKey(mechanism
, CKA_DECRYPT
, key
, param
); 
 476     SECITEM_FreeItem(param
, PR_TRUE
); 
 477     if (ciphercx 
== NULL
) { 
 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; 
 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. 
 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.  
 501 SecCmsCipherContextRef
 
 502 SecCmsCipherContextStartEncrypt(PRArenaPool 
*poolp
, SecSymmetricKeyRef key
, SECAlgorithmID 
*algid
) 
 504     return SecCmsCipherContextStart(poolp
, key
, algid
, PR_TRUE
); 
 506     SecCmsCipherContextRef cc
; 
 510     CK_MECHANISM_TYPE mechanism
; 
 512     Boolean needToEncodeAlgid 
= PR_FALSE
; 
 513     SECOidTag algtag 
= SECOID_GetAlgorithmTag(algid
); 
 515     /* set param and mechanism */ 
 516     if (SEC_PKCS5IsAlgorithmPBEAlg(algid
)) { 
 517         CK_MECHANISM pbeMech
, cryptoMech
; 
 518         CSSM_DATA_PTR pbeParams
; 
 519         SEC_PKCS5KeyAndPassword 
*keyPwd
; 
 521         PORT_Memset(&pbeMech
, 0, sizeof(CK_MECHANISM
)); 
 522         PORT_Memset(&cryptoMech
, 0, sizeof(CK_MECHANISM
)); 
 525          * in this case, key is not actually a SecSymmetricKeyRef, but a SEC_PKCS5KeyAndPassword * 
 527         keyPwd 
= (SEC_PKCS5KeyAndPassword 
*)key
; 
 530         /* find correct PK11 mechanism and parameters to initialize pbeMech */ 
 531         pbeMech
.mechanism 
= PK11_AlgtagToMechanism(algtag
); 
 532         pbeParams 
= PK11_ParamFromAlgid(algid
); 
 535         pbeMech
.pParameter 
= pbeParams
->Data
; 
 536         pbeMech
.ulParameterLen 
= pbeParams
->Length
; 
 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
); 
 544         SECITEM_ZfreeItem(pbeParams
, PR_TRUE
); 
 546         /* and use it to initialize param & mechanism */ 
 547         if ((param 
= (CSSM_DATA_PTR
)PORT_ZAlloc(sizeof(CSSM_DATA
))) == NULL
) 
 550         param
->Data 
= (unsigned char *)cryptoMech
.pParameter
; 
 551         param
->Length 
= cryptoMech
.ulParameterLen
; 
 552         mechanism 
= cryptoMech
.mechanism
; 
 554         mechanism 
= PK11_AlgtagToMechanism(algtag
); 
 555         if ((param 
= PK11_GenerateNewParam(mechanism
, key
)) == NULL
) 
 557         needToEncodeAlgid 
= PR_TRUE
; 
 560     cc 
= (SecCmsCipherContextRef
)PORT_ZAlloc(sizeof(SecCmsCipherContext
)); 
 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
; 
 570     /* and here we go, creating a PK11 cipher context */ 
 571     ciphercx 
= PK11_CreateContextBySymKey(mechanism
, CKA_ENCRYPT
, key
, param
); 
 572     if (ciphercx 
== NULL
) { 
 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? 
 586     if (needToEncodeAlgid
) { 
 587         rv 
= PK11_ParamToAlgid(algtag
, param
, poolp
, algid
); 
 588         if(rv 
!= SECSuccess
) { 
 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; 
 602     SECITEM_FreeItem(param
, PR_TRUE
); 
 609 SecCmsCipherContextDestroy(SecCmsCipherContextRef cc
) 
 611     PORT_Assert(cc 
!= NULL
); 
 614     CSSM_DeleteContext(cc
->cc
); 
 619 SecCmsCipherContextLength(SecCmsCipherContextRef cc
, unsigned int input_len
, Boolean final
, Boolean encrypt
) 
 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
); 
 630     return dataBlockSize
[0].SizeOutputBlock
; 
 634  * SecCmsCipherContextDecryptLength - find the output length of the next call to decrypt. 
 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 
 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). 
 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 
 655 SecCmsCipherContextDecryptLength(SecCmsCipherContextRef cc
, size_t input_len
, Boolean final
) 
 658     return SecCmsCipherContextLength(cc
, (unsigned int)input_len
, final
, PR_FALSE
); 
 660     int blocks
, block_size
; 
 662     PORT_Assert (! cc
->encrypt
); 
 664     block_size 
= cc
->block_size
; 
 667      * If this is not a block cipher, then we always have the same 
 668      * number of output bytes as we had input bytes. 
 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. 
 682         return cc
->pending_count 
+ input_len
; 
 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 
 694     blocks 
= (cc
->pending_count 
+ input_len 
- 1) / block_size
; 
 695     return blocks 
* block_size
; 
 700  * SecCmsCipherContextEncryptLength - find the output length of the next call to encrypt. 
 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 
 706  * Result can be used to perform memory allocations. 
 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 
 717 SecCmsCipherContextEncryptLength(SecCmsCipherContextRef cc
, size_t input_len
, Boolean final
) 
 720     return SecCmsCipherContextLength(cc
, (unsigned int)input_len
, final
, PR_TRUE
); 
 722     int blocks
, block_size
; 
 725     PORT_Assert (cc
->encrypt
); 
 727     block_size 
= cc
->block_size
; 
 728     pad_size 
= cc
->pad_size
; 
 731      * If this is not a block cipher, then we always have the same 
 732      * number of output bytes as we had input bytes. 
 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.) 
 745             return cc
->pending_count 
+ input_len
; 
 747             blocks 
= (cc
->pending_count 
+ input_len
) / pad_size
; 
 749             return blocks
*pad_size
; 
 754      * Now, count the number of complete blocks of data we have. 
 756     blocks 
= (cc
->pending_count 
+ input_len
) / block_size
; 
 759     return blocks 
* block_size
; 
 765 SecCmsCipherContextCrypt(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
) 
 770     CSSM_DATA outputBuf 
= { max_output_len
, output 
}; 
 771     CSSM_SIZE bytes_output 
= 0; 
 776         CSSM_DATA inputBuf 
= { input_len
, (uint8 
*)input 
}; 
 779             rv 
= CSSM_EncryptDataUpdate(cc
->cc
, &inputBuf
, 1, &outputBuf
, 1, &bytes_output
); 
 781             rv 
= CSSM_DecryptDataUpdate(cc
->cc
, &inputBuf
, 1, &outputBuf
, 1, &bytes_output
); 
 786         CSSM_DATA remainderBuf 
= { max_output_len 
- bytes_output
, output 
+ bytes_output 
}; 
 788             rv 
= CSSM_EncryptDataFinal(cc
->cc
, &remainderBuf
); 
 790             rv 
= CSSM_DecryptDataFinal(cc
->cc
, &remainderBuf
); 
 792         bytes_output 
+= remainderBuf
.Length
; 
 796         PORT_SetError(SEC_ERROR_BAD_DATA
); 
 797     else if (output_len_p
) 
 798         *output_len_p 
= bytes_output
; 
 804  * SecCmsCipherContextDecrypt - do the decryption 
 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 
 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. 
 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.) 
 834 SecCmsCipherContextDecrypt(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
, 
 840     return SecCmsCipherContextCrypt(cc
, output
, 
 841                   output_len_p
,  max_output_len
, 
 845     int blocks
, bsize
, pcount
, padsize
; 
 846     unsigned int max_needed
, ifraglen
, ofraglen
, output_len
; 
 850     PORT_Assert (! cc
->encrypt
); 
 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). 
 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); */ 
 864      * hardware encryption does not like small decryption sizes here, so we 
 865      * allow both blocking and padding. 
 867     bsize 
= cc
->block_size
; 
 868     padsize 
= cc
->pad_size
; 
 871      * When no blocking or padding work to do, we can simply call the 
 872      * cipher function and we are done. 
 875         return (* cc
->doit
) (cc
->cx
, output
, output_len_p
, max_output_len
, 
 879     pcount 
= cc
->pending_count
; 
 880     pbuf 
= cc
->pending_buf
; 
 886          * Try to fill in an entire block, starting with the bytes 
 887          * we already have saved away. 
 889         while (input_len 
&& pcount 
< bsize
) { 
 890             pbuf
[pcount
++] = *input
++; 
 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.) 
 899         if (input_len 
== 0 && !final
) { 
 900             cc
->pending_count 
= pcount
; 
 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. 
 910         if ((padsize 
!= 0) && (pcount 
% padsize
) != 0) { 
 912             PORT_SetError (SEC_ERROR_BAD_DATA
); 
 918         rv 
= (*cc
->doit
)(cc
->cx
, output
, &ofraglen
, max_output_len
, 
 920         if (rv 
!= SECSuccess
) 
 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! 
 928         PORT_Assert(ofraglen 
== pcount
); 
 931          * Account for the bytes now in output. 
 933         max_output_len 
-= ofraglen
; 
 934         output_len 
+= ofraglen
; 
 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. 
 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. 
 953             blocks 
= input_len 
/ padsize
; 
 954             ifraglen 
= blocks 
* padsize
; 
 955         } else ifraglen 
= input_len
; 
 956         PORT_Assert (ifraglen 
== input_len
); 
 958         if (ifraglen 
!= input_len
) { 
 959             PORT_SetError(SEC_ERROR_BAD_DATA
); 
 963         blocks 
= (input_len 
- 1) / bsize
; 
 964         ifraglen 
= blocks 
* bsize
; 
 965         PORT_Assert (ifraglen 
< input_len
); 
 967         pcount 
= input_len 
- ifraglen
; 
 968         PORT_Memcpy (pbuf
, input 
+ ifraglen
, pcount
); 
 969         cc
->pending_count 
= pcount
; 
 973         rv 
= (* cc
->doit
)(cc
->cx
, output
, &ofraglen
, max_output_len
, 
 975         if (rv 
!= SECSuccess
) 
 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! 
 983         PORT_Assert (ifraglen 
== ofraglen
); 
 984         if (ifraglen 
!= ofraglen
) { 
 985             PORT_SetError(SEC_ERROR_BAD_DATA
); 
 989         output_len 
+= ofraglen
; 
 995      * If we just did our very last block, "remove" the padding by 
 996      * adjusting the output length. 
 998     if (final 
&& (padsize 
!= 0)) { 
 999         unsigned int padlen 
= *(output 
+ ofraglen 
- 1); 
1001         if (padlen 
== 0 || padlen 
> padsize
) { 
1002             PORT_SetError(SEC_ERROR_BAD_DATA
); 
1005         output_len 
-= padlen
; 
1008     PORT_Assert (output_len_p 
!= NULL 
|| output_len 
== 0); 
1009     if (output_len_p 
!= NULL
) 
1010         *output_len_p 
= output_len
; 
1017  * SecCmsCipherContextEncrypt - do the encryption 
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 
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. 
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.) 
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. 
1052 SecCmsCipherContextEncrypt(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
, 
1058     return SecCmsCipherContextCrypt(cc
, output
, 
1059                   output_len_p
,  max_output_len
, 
1063     int blocks
, bsize
, padlen
, pcount
, padsize
; 
1064     unsigned int max_needed
, ifraglen
, ofraglen
, output_len
; 
1065     unsigned char *pbuf
; 
1068     PORT_Assert (cc
->encrypt
); 
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). 
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); */ 
1081     bsize 
= cc
->block_size
; 
1082     padsize 
= cc
->pad_size
; 
1085      * When no blocking and padding work to do, we can simply call the 
1086      * cipher function and we are done. 
1089         return (*cc
->doit
)(cc
->cx
, output
, output_len_p
, max_output_len
, 
1093     pcount 
= cc
->pending_count
; 
1094     pbuf 
= cc
->pending_buf
; 
1100          * Try to fill in an entire block, starting with the bytes 
1101          * we already have saved away. 
1103         while (input_len 
&& pcount 
< bsize
) { 
1104             pbuf
[pcount
++] = *input
++; 
1108          * If we do not have a full block and we know we will be 
1109          * called again, then we are done for now. 
1111         if (pcount 
< bsize 
&& !final
) { 
1112             cc
->pending_count 
= pcount
; 
1113             if (output_len_p 
!= NULL
) 
1118          * If we have a whole block available, encrypt it. 
1120         if ((padsize 
== 0) || (pcount 
% padsize
) == 0) { 
1121             rv 
= (* cc
->doit
) (cc
->cx
, output
, &ofraglen
, max_output_len
, 
1123             if (rv 
!= SECSuccess
) 
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! 
1131             PORT_Assert (ofraglen 
== pcount
); 
1134              * Account for the bytes now in output. 
1136             max_output_len 
-= ofraglen
; 
1137             output_len 
+= ofraglen
; 
1145         PORT_Assert (pcount 
== 0); 
1147         blocks 
= input_len 
/ bsize
; 
1148         ifraglen 
= blocks 
* bsize
; 
1151             rv 
= (* cc
->doit
) (cc
->cx
, output
, &ofraglen
, max_output_len
, 
1153             if (rv 
!= SECSuccess
) 
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! 
1161             PORT_Assert (ifraglen 
== ofraglen
); 
1163             max_output_len 
-= ofraglen
; 
1164             output_len 
+= ofraglen
; 
1168         pcount 
= input_len 
- ifraglen
; 
1169         PORT_Assert (pcount 
< bsize
); 
1171             PORT_Memcpy (pbuf
, input 
+ ifraglen
, pcount
); 
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
) 
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! 
1187         PORT_Assert (ofraglen 
== (pcount
+padlen
)); 
1188         output_len 
+= ofraglen
; 
1190         cc
->pending_count 
= pcount
; 
1193     PORT_Assert (output_len_p 
!= NULL 
|| output_len 
== 0); 
1194     if (output_len_p 
!= NULL
) 
1195         *output_len_p 
= output_len
;