Back to index

lightning-sunbird  0.9+nobinonly
smimemessage.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  * SMIME message methods
00039  *
00040  * $Id: smimemessage.c,v 1.6 2004/04/25 15:03:16 gerv%gerv.net Exp $
00041  */
00042 
00043 #include "cmslocal.h"
00044 #include "smime.h"
00045 
00046 #include "cert.h"
00047 #include "key.h"
00048 #include "secasn1.h"
00049 #include "secitem.h"
00050 #include "secoid.h"
00051 #include "pk11func.h"
00052 #include "prtime.h"
00053 #include "secerr.h"
00054 
00055 
00056 #if 0
00057 /*
00058  * NSS_SMIMEMessage_CreateEncrypted - start an S/MIME encrypting context.
00059  *
00060  * "scert" is the cert for the sender.  It will be checked for validity.
00061  * "rcerts" are the certs for the recipients.  They will also be checked.
00062  *
00063  * "certdb" is the cert database to use for verifying the certs.
00064  * It can be NULL if a default database is available (like in the client).
00065  *
00066  * This function already does all of the stuff specific to S/MIME protocol
00067  * and local policy; the return value just needs to be passed to
00068  * SEC_PKCS7Encode() or to SEC_PKCS7EncoderStart() to create the encoded data,
00069  * and finally to SEC_PKCS7DestroyContentInfo().
00070  *
00071  * An error results in a return value of NULL and an error set.
00072  * (Retrieve specific errors via PORT_GetError()/XP_GetError().)
00073  */
00074 NSSCMSMessage *
00075 NSS_SMIMEMessage_CreateEncrypted(CERTCertificate *scert,
00076                      CERTCertificate **rcerts,
00077                      CERTCertDBHandle *certdb,
00078                      PK11PasswordFunc pwfn,
00079                      void *pwfn_arg)
00080 {
00081     NSSCMSMessage *cmsg;
00082     long cipher;
00083     SECOidTag encalg;
00084     int keysize;
00085     int mapi, rci;
00086 
00087     cipher = smime_choose_cipher (scert, rcerts);
00088     if (cipher < 0)
00089        return NULL;
00090 
00091     mapi = smime_mapi_by_cipher (cipher);
00092     if (mapi < 0)
00093        return NULL;
00094 
00095     /*
00096      * XXX This is stretching it -- CreateEnvelopedData should probably
00097      * take a cipher itself of some sort, because we cannot know what the
00098      * future will bring in terms of parameters for each type of algorithm.
00099      * For example, just an algorithm and keysize is *not* sufficient to
00100      * fully specify the usage of RC5 (which also needs to know rounds and
00101      * block size).  Work this out into a better API!
00102      */
00103     encalg = smime_cipher_map[mapi].algtag;
00104     keysize = smime_keysize_by_cipher (cipher);
00105     if (keysize < 0)
00106        return NULL;
00107 
00108     cinfo = SEC_PKCS7CreateEnvelopedData (scert, certUsageEmailRecipient,
00109                                      certdb, encalg, keysize,
00110                                      pwfn, pwfn_arg);
00111     if (cinfo == NULL)
00112        return NULL;
00113 
00114     for (rci = 0; rcerts[rci] != NULL; rci++) {
00115        if (rcerts[rci] == scert)
00116            continue;
00117        if (SEC_PKCS7AddRecipient (cinfo, rcerts[rci], certUsageEmailRecipient,
00118                                NULL) != SECSuccess) {
00119            SEC_PKCS7DestroyContentInfo (cinfo);
00120            return NULL;
00121        }
00122     }
00123 
00124     return cinfo;
00125 }
00126 
00127 
00128 /*
00129  * Start an S/MIME signing context.
00130  *
00131  * "scert" is the cert that will be used to sign the data.  It will be
00132  * checked for validity.
00133  *
00134  * "ecert" is the signer's encryption cert.  If it is different from
00135  * scert, then it will be included in the signed message so that the
00136  * recipient can save it for future encryptions.
00137  *
00138  * "certdb" is the cert database to use for verifying the cert.
00139  * It can be NULL if a default database is available (like in the client).
00140  * 
00141  * "digestalg" names the digest algorithm (e.g. SEC_OID_SHA1).
00142  * XXX There should be SECMIME functions for hashing, or the hashing should
00143  * be built into this interface, which we would like because we would
00144  * support more smartcards that way, and then this argument should go away.)
00145  *
00146  * "digest" is the actual digest of the data.  It must be provided in
00147  * the case of detached data or NULL if the content will be included.
00148  *
00149  * This function already does all of the stuff specific to S/MIME protocol
00150  * and local policy; the return value just needs to be passed to
00151  * SEC_PKCS7Encode() or to SEC_PKCS7EncoderStart() to create the encoded data,
00152  * and finally to SEC_PKCS7DestroyContentInfo().
00153  *
00154  * An error results in a return value of NULL and an error set.
00155  * (Retrieve specific errors via PORT_GetError()/XP_GetError().)
00156  */
00157 
00158 NSSCMSMessage *
00159 NSS_SMIMEMessage_CreateSigned(CERTCertificate *scert,
00160                     CERTCertificate *ecert,
00161                     CERTCertDBHandle *certdb,
00162                     SECOidTag digestalgtag,
00163                     SECItem *digest,
00164                     PK11PasswordFunc pwfn,
00165                     void *pwfn_arg)
00166 {
00167     NSSCMSMessage *cmsg;
00168     NSSCMSSignedData *sigd;
00169     NSSCMSSignerInfo *signerinfo;
00170 
00171     /* See note in header comment above about digestalg. */
00172     /* Doesn't explain this.  PORT_Assert (digestalgtag == SEC_OID_SHA1); */
00173 
00174     cmsg = NSS_CMSMessage_Create(NULL);
00175     if (cmsg == NULL)
00176        return NULL;
00177 
00178     sigd = NSS_CMSSignedData_Create(cmsg);
00179     if (sigd == NULL)
00180        goto loser;
00181 
00182     /* create just one signerinfo */
00183     signerinfo = NSS_CMSSignerInfo_Create(cmsg, scert, digestalgtag);
00184     if (signerinfo == NULL)
00185        goto loser;
00186 
00187     /* Add the signing time to the signerinfo.  */
00188     if (NSS_CMSSignerInfo_AddSigningTime(signerinfo, PR_Now()) != SECSuccess)
00189        goto loser;
00190     
00191     /* and add the SMIME profile */
00192     if (NSS_SMIMESignerInfo_AddSMIMEProfile(signerinfo, scert) != SECSuccess)
00193        goto loser;
00194 
00195     /* now add the signerinfo to the signeddata */
00196     if (NSS_CMSSignedData_AddSignerInfo(sigd, signerinfo) != SECSuccess)
00197        goto loser;
00198 
00199     /* include the signing cert and its entire chain */
00200     /* note that there are no checks for duplicate certs in place, as all the */
00201     /* essential data structures (like set of certificate) are not there */
00202     if (NSS_CMSSignedData_AddCertChain(sigd, scert) != SECSuccess)
00203        goto loser;
00204 
00205     /* If the encryption cert and the signing cert differ, then include
00206      * the encryption cert too. */
00207     if ( ( ecert != NULL ) && ( ecert != scert ) ) {
00208        if (NSS_CMSSignedData_AddCertificate(sigd, ecert) != SECSuccess)
00209            goto loser;
00210     }
00211 
00212     return cmsg;
00213 loser:
00214     if (cmsg)
00215        NSS_CMSMessage_Destroy(cmsg);
00216     return NULL;
00217 }
00218 #endif