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