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  * CMS message methods. 
  38 #include <Security/SecCmsMessage.h> 
  40 #include <Security/SecCmsContentInfo.h> 
  41 #include <Security/SecCmsSignedData.h> 
  45 #include "SecAsn1Item.h" 
  48 #include <security_asn1/secasn1.h> 
  49 #include <security_asn1/secerr.h> 
  50 #include <security_asn1/secport.h> 
  53  * SecCmsMessageCreate - create a CMS message object 
  55  * "poolp" - arena to allocate memory from, or NULL if new arena should be created 
  58 SecCmsMessageCreate(void) 
  61     SecCmsMessageRef cmsg
; 
  63     poolp 
= PORT_NewArena (1024);           /* XXX what is right value? */ 
  67     cmsg 
= (SecCmsMessageRef
)PORT_ArenaZAlloc (poolp
, sizeof(SecCmsMessage
)); 
  69         PORT_FreeArena(poolp
, PR_FALSE
); 
  74     cmsg
->contentInfo
.cmsg 
= cmsg
; 
  81  * SecCmsMessageSetEncodingParams - set up a CMS message object for encoding or decoding 
  83  * "cmsg" - message object 
  84  * "pwfn", pwfn_arg" - callback function for getting token password 
  85  * "decrypt_key_cb", "decrypt_key_cb_arg" - callback function for getting bulk key for encryptedData 
  86  * "detached_digestalgs", "detached_digests" - digests from detached content 
  89 SecCmsMessageSetEncodingParams(SecCmsMessageRef cmsg
, 
  90                         PK11PasswordFunc pwfn
, void *pwfn_arg
, 
  91                         SecCmsGetDecryptKeyCallback decrypt_key_cb
, void *decrypt_key_cb_arg
) 
  94     // @@@ Deal with password stuff. 
  96         PK11_SetPasswordFunc(pwfn
); 
  98     cmsg
->pwfn_arg 
= pwfn_arg
; 
  99     cmsg
->decrypt_key_cb 
= decrypt_key_cb
; 
 100     cmsg
->decrypt_key_cb_arg 
= decrypt_key_cb_arg
; 
 104  * SecCmsMessageDestroy - destroy a CMS message and all of its sub-pieces. 
 107 SecCmsMessageDestroy(SecCmsMessageRef cmsg
) 
 109     PORT_Assert (cmsg
->refCount 
> 0); 
 110     if (cmsg
->refCount 
<= 0)    /* oops */ 
 113     cmsg
->refCount
--;           /* thread safety? */ 
 114     if (cmsg
->refCount 
> 0) 
 117     SecCmsContentInfoDestroy(&(cmsg
->contentInfo
)); 
 119     PORT_FreeArena (cmsg
->poolp
, PR_FALSE
);     /* XXX clear it? */ 
 123  * SecCmsMessageCopy - return a copy of the given message.  
 125  * The copy may be virtual or may be real -- either way, the result needs 
 126  * to be passed to SecCmsMessageDestroy later (as does the original). 
 129 SecCmsMessageCopy(SecCmsMessageRef cmsg
) 
 134     PORT_Assert (cmsg
->refCount 
> 0); 
 136     cmsg
->refCount
++; /* XXX chrisk thread safety? */ 
 141  * SecCmsMessageGetContentInfo - return a pointer to the top level contentInfo 
 144 SecCmsMessageGetContentInfo(SecCmsMessageRef cmsg
) 
 146     return &(cmsg
->contentInfo
); 
 150  * Return a pointer to the actual content.  
 151  * In the case of those types which are encrypted, this returns the *plain* content. 
 152  * In case of nested contentInfos, this descends and retrieves the innermost content. 
 155 SecCmsMessageGetContent(SecCmsMessageRef cmsg
) 
 157     /* this is a shortcut */ 
 158     SecCmsContentInfoRef cinfo 
= SecCmsMessageGetContentInfo(cmsg
); 
 159     const SecAsn1Item 
*pItem 
= SecCmsContentInfoGetInnerContent(cinfo
); 
 164  * SecCmsMessageContentLevelCount - count number of levels of CMS content objects in this message 
 166  * CMS data content objects do not count. 
 169 SecCmsMessageContentLevelCount(SecCmsMessageRef cmsg
) 
 172     SecCmsContentInfoRef cinfo
; 
 174     /* walk down the chain of contentinfos */ 
 175     for (cinfo 
= &(cmsg
->contentInfo
); cinfo 
!= NULL
; ) { 
 177         cinfo 
= SecCmsContentInfoGetChildContentInfo(cinfo
); 
 183  * SecCmsMessageContentLevel - find content level #n 
 185  * CMS data content objects do not count. 
 188 SecCmsMessageContentLevel(SecCmsMessageRef cmsg
, int n
) 
 191     SecCmsContentInfoRef cinfo
; 
 193     /* walk down the chain of contentinfos */ 
 194     for (cinfo 
= &(cmsg
->contentInfo
); cinfo 
!= NULL 
&& count 
< n
; cinfo 
= SecCmsContentInfoGetChildContentInfo(cinfo
)) { 
 202  * SecCmsMessageContainsCertsOrCrls - see if message contains certs along the way 
 205 SecCmsMessageContainsCertsOrCrls(SecCmsMessageRef cmsg
) 
 207     SecCmsContentInfoRef cinfo
; 
 209     /* descend into CMS message */ 
 210     for (cinfo 
= &(cmsg
->contentInfo
); cinfo 
!= NULL
; cinfo 
= SecCmsContentInfoGetChildContentInfo(cinfo
)) { 
 211         if (SecCmsContentInfoGetContentTypeTag(cinfo
) != SEC_OID_PKCS7_SIGNED_DATA
) 
 212             continue;   /* next level */ 
 214         if (SecCmsSignedDataContainsCertsOrCrls(cinfo
->content
.signedData
)) 
 221  * SecCmsMessageIsEncrypted - see if message contains a encrypted submessage 
 224 SecCmsMessageIsEncrypted(SecCmsMessageRef cmsg
) 
 226     SecCmsContentInfoRef cinfo
; 
 228     /* walk down the chain of contentinfos */ 
 229     for (cinfo 
= &(cmsg
->contentInfo
); cinfo 
!= NULL
; cinfo 
= SecCmsContentInfoGetChildContentInfo(cinfo
)) 
 231         switch (SecCmsContentInfoGetContentTypeTag(cinfo
)) { 
 232         case SEC_OID_PKCS7_ENVELOPED_DATA
: 
 233         case SEC_OID_PKCS7_ENCRYPTED_DATA
: 
 243  * SecCmsMessageIsSigned - see if message contains a signed submessage 
 245  * If the CMS message has a SignedData with a signature (not just a SignedData) 
 246  * return true; false otherwise.  This can/should be called before calling 
 247  * VerifySignature, which will always indicate failure if no signature is 
 248  * present, but that does not mean there even was a signature! 
 249  * Note that the content itself can be empty (detached content was sent 
 250  * another way); it is the presence of the signature that matters. 
 253 SecCmsMessageIsSigned(SecCmsMessageRef cmsg
) 
 255     SecCmsContentInfoRef cinfo
; 
 257     /* walk down the chain of contentinfos */ 
 258     for (cinfo 
= &(cmsg
->contentInfo
); cinfo 
!= NULL
; cinfo 
= SecCmsContentInfoGetChildContentInfo(cinfo
)) 
 260         switch (SecCmsContentInfoGetContentTypeTag(cinfo
)) { 
 261         case SEC_OID_PKCS7_SIGNED_DATA
: 
 262             if (!SecCmsArrayIsEmpty((void **)cinfo
->content
.signedData
->signerInfos
)) 
 273  * SecCmsMessageIsContentEmpty - see if content is empty 
 275  * returns PR_TRUE is innermost content length is < minLen 
 276  * XXX need the encrypted content length (why?) 
 279 SecCmsMessageIsContentEmpty(SecCmsMessageRef cmsg
, unsigned int minLen
) 
 281     SecAsn1Item 
* item 
= NULL
; 
 286     item 
= SecCmsContentInfoGetContent(SecCmsMessageGetContentInfo(cmsg
)); 
 290     } else if(item
->Length 
<= minLen
) {