security/nss/lib/smime/smimemessage.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/smime/smimemessage.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,184 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +/*
     1.9 + * SMIME message methods
    1.10 + */
    1.11 +
    1.12 +#include "cmslocal.h"
    1.13 +#include "smime.h"
    1.14 +
    1.15 +#include "cert.h"
    1.16 +#include "key.h"
    1.17 +#include "secasn1.h"
    1.18 +#include "secitem.h"
    1.19 +#include "secoid.h"
    1.20 +#include "pk11func.h"
    1.21 +#include "prtime.h"
    1.22 +#include "secerr.h"
    1.23 +
    1.24 +
    1.25 +#if 0
    1.26 +/*
    1.27 + * NSS_SMIMEMessage_CreateEncrypted - start an S/MIME encrypting context.
    1.28 + *
    1.29 + * "scert" is the cert for the sender.  It will be checked for validity.
    1.30 + * "rcerts" are the certs for the recipients.  They will also be checked.
    1.31 + *
    1.32 + * "certdb" is the cert database to use for verifying the certs.
    1.33 + * It can be NULL if a default database is available (like in the client).
    1.34 + *
    1.35 + * This function already does all of the stuff specific to S/MIME protocol
    1.36 + * and local policy; the return value just needs to be passed to
    1.37 + * SEC_PKCS7Encode() or to SEC_PKCS7EncoderStart() to create the encoded data,
    1.38 + * and finally to SEC_PKCS7DestroyContentInfo().
    1.39 + *
    1.40 + * An error results in a return value of NULL and an error set.
    1.41 + * (Retrieve specific errors via PORT_GetError()/XP_GetError().)
    1.42 + */
    1.43 +NSSCMSMessage *
    1.44 +NSS_SMIMEMessage_CreateEncrypted(CERTCertificate *scert,
    1.45 +			CERTCertificate **rcerts,
    1.46 +			CERTCertDBHandle *certdb,
    1.47 +			PK11PasswordFunc pwfn,
    1.48 +			void *pwfn_arg)
    1.49 +{
    1.50 +    NSSCMSMessage *cmsg;
    1.51 +    long cipher;
    1.52 +    SECOidTag encalg;
    1.53 +    int keysize;
    1.54 +    int mapi, rci;
    1.55 +
    1.56 +    cipher = smime_choose_cipher (scert, rcerts);
    1.57 +    if (cipher < 0)
    1.58 +	return NULL;
    1.59 +
    1.60 +    mapi = smime_mapi_by_cipher (cipher);
    1.61 +    if (mapi < 0)
    1.62 +	return NULL;
    1.63 +
    1.64 +    /*
    1.65 +     * XXX This is stretching it -- CreateEnvelopedData should probably
    1.66 +     * take a cipher itself of some sort, because we cannot know what the
    1.67 +     * future will bring in terms of parameters for each type of algorithm.
    1.68 +     * For example, just an algorithm and keysize is *not* sufficient to
    1.69 +     * fully specify the usage of RC5 (which also needs to know rounds and
    1.70 +     * block size).  Work this out into a better API!
    1.71 +     */
    1.72 +    encalg = smime_cipher_map[mapi].algtag;
    1.73 +    keysize = smime_keysize_by_cipher (cipher);
    1.74 +    if (keysize < 0)
    1.75 +	return NULL;
    1.76 +
    1.77 +    cinfo = SEC_PKCS7CreateEnvelopedData (scert, certUsageEmailRecipient,
    1.78 +					  certdb, encalg, keysize,
    1.79 +					  pwfn, pwfn_arg);
    1.80 +    if (cinfo == NULL)
    1.81 +	return NULL;
    1.82 +
    1.83 +    for (rci = 0; rcerts[rci] != NULL; rci++) {
    1.84 +	if (rcerts[rci] == scert)
    1.85 +	    continue;
    1.86 +	if (SEC_PKCS7AddRecipient (cinfo, rcerts[rci], certUsageEmailRecipient,
    1.87 +				   NULL) != SECSuccess) {
    1.88 +	    SEC_PKCS7DestroyContentInfo (cinfo);
    1.89 +	    return NULL;
    1.90 +	}
    1.91 +    }
    1.92 +
    1.93 +    return cinfo;
    1.94 +}
    1.95 +
    1.96 +
    1.97 +/*
    1.98 + * Start an S/MIME signing context.
    1.99 + *
   1.100 + * "scert" is the cert that will be used to sign the data.  It will be
   1.101 + * checked for validity.
   1.102 + *
   1.103 + * "ecert" is the signer's encryption cert.  If it is different from
   1.104 + * scert, then it will be included in the signed message so that the
   1.105 + * recipient can save it for future encryptions.
   1.106 + *
   1.107 + * "certdb" is the cert database to use for verifying the cert.
   1.108 + * It can be NULL if a default database is available (like in the client).
   1.109 + * 
   1.110 + * "digestalg" names the digest algorithm (e.g. SEC_OID_SHA1).
   1.111 + * XXX There should be SECMIME functions for hashing, or the hashing should
   1.112 + * be built into this interface, which we would like because we would
   1.113 + * support more smartcards that way, and then this argument should go away.)
   1.114 + *
   1.115 + * "digest" is the actual digest of the data.  It must be provided in
   1.116 + * the case of detached data or NULL if the content will be included.
   1.117 + *
   1.118 + * This function already does all of the stuff specific to S/MIME protocol
   1.119 + * and local policy; the return value just needs to be passed to
   1.120 + * SEC_PKCS7Encode() or to SEC_PKCS7EncoderStart() to create the encoded data,
   1.121 + * and finally to SEC_PKCS7DestroyContentInfo().
   1.122 + *
   1.123 + * An error results in a return value of NULL and an error set.
   1.124 + * (Retrieve specific errors via PORT_GetError()/XP_GetError().)
   1.125 + */
   1.126 +
   1.127 +NSSCMSMessage *
   1.128 +NSS_SMIMEMessage_CreateSigned(CERTCertificate *scert,
   1.129 +		      CERTCertificate *ecert,
   1.130 +		      CERTCertDBHandle *certdb,
   1.131 +		      SECOidTag digestalgtag,
   1.132 +		      SECItem *digest,
   1.133 +		      PK11PasswordFunc pwfn,
   1.134 +		      void *pwfn_arg)
   1.135 +{
   1.136 +    NSSCMSMessage *cmsg;
   1.137 +    NSSCMSSignedData *sigd;
   1.138 +    NSSCMSSignerInfo *signerinfo;
   1.139 +
   1.140 +    /* See note in header comment above about digestalg. */
   1.141 +    /* Doesn't explain this.  PORT_Assert (digestalgtag == SEC_OID_SHA1); */
   1.142 +
   1.143 +    cmsg = NSS_CMSMessage_Create(NULL);
   1.144 +    if (cmsg == NULL)
   1.145 +	return NULL;
   1.146 +
   1.147 +    sigd = NSS_CMSSignedData_Create(cmsg);
   1.148 +    if (sigd == NULL)
   1.149 +	goto loser;
   1.150 +
   1.151 +    /* create just one signerinfo */
   1.152 +    signerinfo = NSS_CMSSignerInfo_Create(cmsg, scert, digestalgtag);
   1.153 +    if (signerinfo == NULL)
   1.154 +	goto loser;
   1.155 +
   1.156 +    /* Add the signing time to the signerinfo.  */
   1.157 +    if (NSS_CMSSignerInfo_AddSigningTime(signerinfo, PR_Now()) != SECSuccess)
   1.158 +	goto loser;
   1.159 +    
   1.160 +    /* and add the SMIME profile */
   1.161 +    if (NSS_SMIMESignerInfo_AddSMIMEProfile(signerinfo, scert) != SECSuccess)
   1.162 +	goto loser;
   1.163 +
   1.164 +    /* now add the signerinfo to the signeddata */
   1.165 +    if (NSS_CMSSignedData_AddSignerInfo(sigd, signerinfo) != SECSuccess)
   1.166 +	goto loser;
   1.167 +
   1.168 +    /* include the signing cert and its entire chain */
   1.169 +    /* note that there are no checks for duplicate certs in place, as all the */
   1.170 +    /* essential data structures (like set of certificate) are not there */
   1.171 +    if (NSS_CMSSignedData_AddCertChain(sigd, scert) != SECSuccess)
   1.172 +	goto loser;
   1.173 +
   1.174 +    /* If the encryption cert and the signing cert differ, then include
   1.175 +     * the encryption cert too. */
   1.176 +    if ( ( ecert != NULL ) && ( ecert != scert ) ) {
   1.177 +	if (NSS_CMSSignedData_AddCertificate(sigd, ecert) != SECSuccess)
   1.178 +	    goto loser;
   1.179 +    }
   1.180 +
   1.181 +    return cmsg;
   1.182 +loser:
   1.183 +    if (cmsg)
   1.184 +	NSS_CMSMessage_Destroy(cmsg);
   1.185 +    return NULL;
   1.186 +}
   1.187 +#endif

mercurial