smimemessage.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. /*
  5. * SMIME message methods
  6. */
  7. #include "cmslocal.h"
  8. #include "smime.h"
  9. #include "cert.h"
  10. #include "keyhi.h"
  11. #include "secasn1.h"
  12. #include "secitem.h"
  13. #include "secoid.h"
  14. #include "pk11func.h"
  15. #include "prtime.h"
  16. #include "secerr.h"
  17. #if 0
  18. /*
  19. * NSS_SMIMEMessage_CreateEncrypted - start an S/MIME encrypting context.
  20. *
  21. * "scert" is the cert for the sender. It will be checked for validity.
  22. * "rcerts" are the certs for the recipients. They will also be checked.
  23. *
  24. * "certdb" is the cert database to use for verifying the certs.
  25. * It can be NULL if a default database is available (like in the client).
  26. *
  27. * This function already does all of the stuff specific to S/MIME protocol
  28. * and local policy; the return value just needs to be passed to
  29. * SEC_PKCS7Encode() or to SEC_PKCS7EncoderStart() to create the encoded data,
  30. * and finally to SEC_PKCS7DestroyContentInfo().
  31. *
  32. * An error results in a return value of NULL and an error set.
  33. * (Retrieve specific errors via PORT_GetError()/XP_GetError().)
  34. */
  35. NSSCMSMessage *
  36. NSS_SMIMEMessage_CreateEncrypted(CERTCertificate *scert,
  37. CERTCertificate **rcerts,
  38. CERTCertDBHandle *certdb,
  39. PK11PasswordFunc pwfn,
  40. void *pwfn_arg)
  41. {
  42. NSSCMSMessage *cmsg;
  43. long cipher;
  44. SECOidTag encalg;
  45. int keysize;
  46. int mapi, rci;
  47. cipher = smime_choose_cipher (scert, rcerts);
  48. if (cipher < 0)
  49. return NULL;
  50. mapi = smime_mapi_by_cipher (cipher);
  51. if (mapi < 0)
  52. return NULL;
  53. /*
  54. * XXX This is stretching it -- CreateEnvelopedData should probably
  55. * take a cipher itself of some sort, because we cannot know what the
  56. * future will bring in terms of parameters for each type of algorithm.
  57. * For example, just an algorithm and keysize is *not* sufficient to
  58. * fully specify the usage of RC5 (which also needs to know rounds and
  59. * block size). Work this out into a better API!
  60. */
  61. encalg = smime_cipher_map[mapi].algtag;
  62. keysize = smime_keysize_by_cipher (cipher);
  63. if (keysize < 0)
  64. return NULL;
  65. cinfo = SEC_PKCS7CreateEnvelopedData (scert, certUsageEmailRecipient,
  66. certdb, encalg, keysize,
  67. pwfn, pwfn_arg);
  68. if (cinfo == NULL)
  69. return NULL;
  70. for (rci = 0; rcerts[rci] != NULL; rci++) {
  71. if (rcerts[rci] == scert)
  72. continue;
  73. if (SEC_PKCS7AddRecipient (cinfo, rcerts[rci], certUsageEmailRecipient,
  74. NULL) != SECSuccess) {
  75. SEC_PKCS7DestroyContentInfo (cinfo);
  76. return NULL;
  77. }
  78. }
  79. return cinfo;
  80. }
  81. /*
  82. * Start an S/MIME signing context.
  83. *
  84. * "scert" is the cert that will be used to sign the data. It will be
  85. * checked for validity.
  86. *
  87. * "ecert" is the signer's encryption cert. If it is different from
  88. * scert, then it will be included in the signed message so that the
  89. * recipient can save it for future encryptions.
  90. *
  91. * "certdb" is the cert database to use for verifying the cert.
  92. * It can be NULL if a default database is available (like in the client).
  93. *
  94. * "digestalg" names the digest algorithm (e.g. SEC_OID_SHA1).
  95. * XXX There should be SECMIME functions for hashing, or the hashing should
  96. * be built into this interface, which we would like because we would
  97. * support more smartcards that way, and then this argument should go away.)
  98. *
  99. * "digest" is the actual digest of the data. It must be provided in
  100. * the case of detached data or NULL if the content will be included.
  101. *
  102. * This function already does all of the stuff specific to S/MIME protocol
  103. * and local policy; the return value just needs to be passed to
  104. * SEC_PKCS7Encode() or to SEC_PKCS7EncoderStart() to create the encoded data,
  105. * and finally to SEC_PKCS7DestroyContentInfo().
  106. *
  107. * An error results in a return value of NULL and an error set.
  108. * (Retrieve specific errors via PORT_GetError()/XP_GetError().)
  109. */
  110. NSSCMSMessage *
  111. NSS_SMIMEMessage_CreateSigned(CERTCertificate *scert,
  112. CERTCertificate *ecert,
  113. CERTCertDBHandle *certdb,
  114. SECOidTag digestalgtag,
  115. SECItem *digest,
  116. PK11PasswordFunc pwfn,
  117. void *pwfn_arg)
  118. {
  119. NSSCMSMessage *cmsg;
  120. NSSCMSSignedData *sigd;
  121. NSSCMSSignerInfo *signerinfo;
  122. /* See note in header comment above about digestalg. */
  123. /* Doesn't explain this. PORT_Assert (digestalgtag == SEC_OID_SHA1); */
  124. cmsg = NSS_CMSMessage_Create(NULL);
  125. if (cmsg == NULL)
  126. return NULL;
  127. sigd = NSS_CMSSignedData_Create(cmsg);
  128. if (sigd == NULL)
  129. goto loser;
  130. /* create just one signerinfo */
  131. signerinfo = NSS_CMSSignerInfo_Create(cmsg, scert, digestalgtag);
  132. if (signerinfo == NULL)
  133. goto loser;
  134. /* Add the signing time to the signerinfo. */
  135. if (NSS_CMSSignerInfo_AddSigningTime(signerinfo, PR_Now()) != SECSuccess)
  136. goto loser;
  137. /* and add the SMIME profile */
  138. if (NSS_SMIMESignerInfo_AddSMIMEProfile(signerinfo, scert) != SECSuccess)
  139. goto loser;
  140. /* now add the signerinfo to the signeddata */
  141. if (NSS_CMSSignedData_AddSignerInfo(sigd, signerinfo) != SECSuccess)
  142. goto loser;
  143. /* include the signing cert and its entire chain */
  144. /* note that there are no checks for duplicate certs in place, as all the */
  145. /* essential data structures (like set of certificate) are not there */
  146. if (NSS_CMSSignedData_AddCertChain(sigd, scert) != SECSuccess)
  147. goto loser;
  148. /* If the encryption cert and the signing cert differ, then include
  149. * the encryption cert too. */
  150. if ( ( ecert != NULL ) && ( ecert != scert ) ) {
  151. if (NSS_CMSSignedData_AddCertificate(sigd, ecert) != SECSuccess)
  152. goto loser;
  153. }
  154. return cmsg;
  155. loser:
  156. if (cmsg)
  157. NSS_CMSMessage_Destroy(cmsg);
  158. return NULL;
  159. }
  160. #endif