Back to index

lightning-sunbird  0.9+nobinonly
cmscinfo.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 /*
00038  * CMS contentInfo methods.
00039  *
00040  * $Id: cmscinfo.c,v 1.7 2004/04/25 15:03:16 gerv%gerv.net Exp $
00041  */
00042 
00043 #include "cmslocal.h"
00044 
00045 #include "pk11func.h"
00046 #include "secitem.h"
00047 #include "secoid.h"
00048 #include "secerr.h"
00049 
00050 /*
00051  * NSS_CMSContentInfo_Create - create a content info
00052  *
00053  * version is set in the _Finalize procedures for each content type
00054  */
00055 
00056 /*
00057  * NSS_CMSContentInfo_Destroy - destroy a CMS contentInfo and all of its sub-pieces.
00058  */
00059 void
00060 NSS_CMSContentInfo_Destroy(NSSCMSContentInfo *cinfo)
00061 {
00062     SECOidTag kind;
00063 
00064     kind = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
00065     switch (kind) {
00066     case SEC_OID_PKCS7_ENVELOPED_DATA:
00067        NSS_CMSEnvelopedData_Destroy(cinfo->content.envelopedData);
00068        break;
00069       case SEC_OID_PKCS7_SIGNED_DATA:
00070        NSS_CMSSignedData_Destroy(cinfo->content.signedData);
00071        break;
00072       case SEC_OID_PKCS7_ENCRYPTED_DATA:
00073        NSS_CMSEncryptedData_Destroy(cinfo->content.encryptedData);
00074        break;
00075       case SEC_OID_PKCS7_DIGESTED_DATA:
00076        NSS_CMSDigestedData_Destroy(cinfo->content.digestedData);
00077        break;
00078       default:
00079        /* XXX Anything else that needs to be "manually" freed/destroyed? */
00080        break;
00081     }
00082     if (cinfo->digcx) {
00083        /* must destroy digest objects */
00084        NSS_CMSDigestContext_Cancel(cinfo->digcx);
00085        cinfo->digcx = NULL;
00086     }
00087     if (cinfo->bulkkey)
00088        PK11_FreeSymKey(cinfo->bulkkey);
00089 
00090     if (cinfo->ciphcx) {
00091        NSS_CMSCipherContext_Destroy(cinfo->ciphcx);
00092        cinfo->ciphcx = NULL;
00093     }
00094     
00095     /* we live in a pool, so no need to worry about storage */
00096 }
00097 
00098 /*
00099  * NSS_CMSContentInfo_GetChildContentInfo - get content's contentInfo (if it exists)
00100  */
00101 NSSCMSContentInfo *
00102 NSS_CMSContentInfo_GetChildContentInfo(NSSCMSContentInfo *cinfo)
00103 {
00104     void * ptr                  = NULL;
00105     NSSCMSContentInfo * ccinfo  = NULL;
00106     SECOidTag tag = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
00107     switch (tag) {
00108     case SEC_OID_PKCS7_SIGNED_DATA:
00109        ptr    = (void *)cinfo->content.signedData;
00110        ccinfo = &(cinfo->content.signedData->contentInfo);
00111        break;
00112     case SEC_OID_PKCS7_ENVELOPED_DATA:
00113        ptr    = (void *)cinfo->content.envelopedData;
00114        ccinfo = &(cinfo->content.envelopedData->contentInfo);
00115        break;
00116     case SEC_OID_PKCS7_DIGESTED_DATA:
00117        ptr    = (void *)cinfo->content.digestedData;
00118        ccinfo = &(cinfo->content.digestedData->contentInfo);
00119        break;
00120     case SEC_OID_PKCS7_ENCRYPTED_DATA:
00121        ptr    = (void *)cinfo->content.encryptedData;
00122        ccinfo = &(cinfo->content.encryptedData->contentInfo);
00123        break;
00124     case SEC_OID_PKCS7_DATA:
00125     default:
00126        break;
00127     }
00128     return (ptr ? ccinfo : NULL);
00129 }
00130 
00131 /*
00132  * NSS_CMSContentInfo_SetContent - set content type & content
00133  */
00134 SECStatus
00135 NSS_CMSContentInfo_SetContent(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo, SECOidTag type, void *ptr)
00136 {
00137     SECStatus rv;
00138 
00139     cinfo->contentTypeTag = SECOID_FindOIDByTag(type);
00140     if (cinfo->contentTypeTag == NULL)
00141        return SECFailure;
00142     
00143     /* do not copy the oid, just create a reference */
00144     rv = SECITEM_CopyItem (cmsg->poolp, &(cinfo->contentType), &(cinfo->contentTypeTag->oid));
00145     if (rv != SECSuccess)
00146        return SECFailure;
00147 
00148     cinfo->content.pointer = ptr;
00149 
00150     if (type != SEC_OID_PKCS7_DATA) {
00151        /* as we always have some inner data,
00152         * we need to set it to something, just to fool the encoder enough to work on it
00153         * and get us into nss_cms_encoder_notify at that point */
00154        cinfo->rawContent = SECITEM_AllocItem(cmsg->poolp, NULL, 1);
00155        if (cinfo->rawContent == NULL) {
00156            PORT_SetError(SEC_ERROR_NO_MEMORY);
00157            return SECFailure;
00158        }
00159     }
00160 
00161     return SECSuccess;
00162 }
00163 
00164 /*
00165  * NSS_CMSContentInfo_SetContent_XXXX - typesafe wrappers for NSS_CMSContentInfo_SetContent
00166  */
00167 
00168 /*
00169  * data == NULL -> pass in data via NSS_CMSEncoder_Update
00170  * data != NULL -> take this data
00171  */
00172 SECStatus
00173 NSS_CMSContentInfo_SetContent_Data(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo, SECItem *data, PRBool detached)
00174 {
00175     if (NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_DATA, (void *)data) != SECSuccess)
00176        return SECFailure;
00177     cinfo->rawContent = (detached) ? 
00178                          NULL : (data) ? 
00179                             data : SECITEM_AllocItem(cmsg->poolp, NULL, 1);
00180     return SECSuccess;
00181 }
00182 
00183 SECStatus
00184 NSS_CMSContentInfo_SetContent_SignedData(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo, NSSCMSSignedData *sigd)
00185 {
00186     return NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_SIGNED_DATA, (void *)sigd);
00187 }
00188 
00189 SECStatus
00190 NSS_CMSContentInfo_SetContent_EnvelopedData(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo, NSSCMSEnvelopedData *envd)
00191 {
00192     return NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_ENVELOPED_DATA, (void *)envd);
00193 }
00194 
00195 SECStatus
00196 NSS_CMSContentInfo_SetContent_DigestedData(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo, NSSCMSDigestedData *digd)
00197 {
00198     return NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_DIGESTED_DATA, (void *)digd);
00199 }
00200 
00201 SECStatus
00202 NSS_CMSContentInfo_SetContent_EncryptedData(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo, NSSCMSEncryptedData *encd)
00203 {
00204     return NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_ENCRYPTED_DATA, (void *)encd);
00205 }
00206 
00207 /*
00208  * NSS_CMSContentInfo_GetContent - get pointer to inner content
00209  *
00210  * needs to be casted...
00211  */
00212 void *
00213 NSS_CMSContentInfo_GetContent(NSSCMSContentInfo *cinfo)
00214 {
00215     SECOidTag tag = (cinfo && cinfo->contentTypeTag) 
00216                        ? cinfo->contentTypeTag->offset 
00217                        : SEC_OID_UNKNOWN;
00218     switch (tag) {
00219     case SEC_OID_PKCS7_DATA:
00220     case SEC_OID_PKCS7_SIGNED_DATA:
00221     case SEC_OID_PKCS7_ENVELOPED_DATA:
00222     case SEC_OID_PKCS7_DIGESTED_DATA:
00223     case SEC_OID_PKCS7_ENCRYPTED_DATA:
00224        return cinfo->content.pointer;
00225     default:
00226        return NULL;
00227     }
00228 }
00229 
00230 /* 
00231  * NSS_CMSContentInfo_GetInnerContent - get pointer to innermost content
00232  *
00233  * this is typically only called by NSS_CMSMessage_GetContent()
00234  */
00235 SECItem *
00236 NSS_CMSContentInfo_GetInnerContent(NSSCMSContentInfo *cinfo)
00237 {
00238     NSSCMSContentInfo *ccinfo;
00239     SECOidTag          tag;
00240     SECItem           *pItem = NULL;
00241 
00242     tag = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
00243     switch (tag) {
00244     case SEC_OID_PKCS7_DATA:
00245        /* end of recursion - every message has to have a data cinfo */
00246        pItem = cinfo->content.data; 
00247        break;
00248     case SEC_OID_PKCS7_DIGESTED_DATA:
00249     case SEC_OID_PKCS7_ENCRYPTED_DATA:
00250     case SEC_OID_PKCS7_ENVELOPED_DATA:
00251     case SEC_OID_PKCS7_SIGNED_DATA:
00252        ccinfo = NSS_CMSContentInfo_GetChildContentInfo(cinfo);
00253        if (ccinfo != NULL)
00254            pItem = NSS_CMSContentInfo_GetContent(ccinfo);
00255        break;
00256     default:
00257        PORT_Assert(0);
00258        break;
00259     }
00260     return pItem;
00261 }
00262 
00263 /*
00264  * NSS_CMSContentInfo_GetContentType{Tag,OID} - find out (saving pointer to lookup result
00265  * for future reference) and return the inner content type.
00266  */
00267 SECOidTag
00268 NSS_CMSContentInfo_GetContentTypeTag(NSSCMSContentInfo *cinfo)
00269 {
00270     if (cinfo->contentTypeTag == NULL)
00271        cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType));
00272 
00273     if (cinfo->contentTypeTag == NULL)
00274        return SEC_OID_UNKNOWN;
00275 
00276     return cinfo->contentTypeTag->offset;
00277 }
00278 
00279 SECItem *
00280 NSS_CMSContentInfo_GetContentTypeOID(NSSCMSContentInfo *cinfo)
00281 {
00282     if (cinfo->contentTypeTag == NULL)
00283        cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType));
00284 
00285     if (cinfo->contentTypeTag == NULL)
00286        return NULL;
00287 
00288     return &(cinfo->contentTypeTag->oid);
00289 }
00290 
00291 /*
00292  * NSS_CMSContentInfo_GetContentEncAlgTag - find out (saving pointer to lookup result
00293  * for future reference) and return the content encryption algorithm tag.
00294  */
00295 SECOidTag
00296 NSS_CMSContentInfo_GetContentEncAlgTag(NSSCMSContentInfo *cinfo)
00297 {
00298     if (cinfo->contentEncAlgTag == SEC_OID_UNKNOWN)
00299        cinfo->contentEncAlgTag = SECOID_GetAlgorithmTag(&(cinfo->contentEncAlg));
00300 
00301     return cinfo->contentEncAlgTag;
00302 }
00303 
00304 /*
00305  * NSS_CMSContentInfo_GetContentEncAlg - find out and return the content encryption algorithm tag.
00306  */
00307 SECAlgorithmID *
00308 NSS_CMSContentInfo_GetContentEncAlg(NSSCMSContentInfo *cinfo)
00309 {
00310     return &(cinfo->contentEncAlg);
00311 }
00312 
00313 SECStatus
00314 NSS_CMSContentInfo_SetContentEncAlg(PLArenaPool *poolp, NSSCMSContentInfo *cinfo,
00315                                 SECOidTag bulkalgtag, SECItem *parameters, int keysize)
00316 {
00317     SECStatus rv;
00318 
00319     rv = SECOID_SetAlgorithmID(poolp, &(cinfo->contentEncAlg), bulkalgtag, parameters);
00320     if (rv != SECSuccess)
00321        return SECFailure;
00322     cinfo->keysize = keysize;
00323     return SECSuccess;
00324 }
00325 
00326 SECStatus
00327 NSS_CMSContentInfo_SetContentEncAlgID(PLArenaPool *poolp, NSSCMSContentInfo *cinfo,
00328                                 SECAlgorithmID *algid, int keysize)
00329 {
00330     SECStatus rv;
00331 
00332     rv = SECOID_CopyAlgorithmID(poolp, &(cinfo->contentEncAlg), algid);
00333     if (rv != SECSuccess)
00334        return SECFailure;
00335     if (keysize >= 0)
00336        cinfo->keysize = keysize;
00337     return SECSuccess;
00338 }
00339 
00340 void
00341 NSS_CMSContentInfo_SetBulkKey(NSSCMSContentInfo *cinfo, PK11SymKey *bulkkey)
00342 {
00343     cinfo->bulkkey = PK11_ReferenceSymKey(bulkkey);
00344     cinfo->keysize = PK11_GetKeyStrength(cinfo->bulkkey, &(cinfo->contentEncAlg));
00345 }
00346 
00347 PK11SymKey *
00348 NSS_CMSContentInfo_GetBulkKey(NSSCMSContentInfo *cinfo)
00349 {
00350     if (cinfo->bulkkey == NULL)
00351        return NULL;
00352 
00353     return PK11_ReferenceSymKey(cinfo->bulkkey);
00354 }
00355 
00356 int
00357 NSS_CMSContentInfo_GetBulkKeySize(NSSCMSContentInfo *cinfo)
00358 {
00359     return cinfo->keysize;
00360 }