/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
 * SMIME message methods
 */

#include "cmslocal.h"
#include "smime.h"

#include "cert.h"
#include "keyhi.h"
#include "secasn1.h"
#include "secitem.h"
#include "secoid.h"
#include "pk11func.h"
#include "prtime.h"
#include "secerr.h"

#if 0
/*
 * NSS_SMIMEMessage_CreateEncrypted - start an S/MIME encrypting context.
 *
 * "scert" is the cert for the sender.  It will be checked for validity.
 * "rcerts" are the certs for the recipients.  They will also be checked.
 *
 * "certdb" is the cert database to use for verifying the certs.
 * It can be NULL if a default database is available (like in the client).
 *
 * This function already does all of the stuff specific to S/MIME protocol
 * and local policy; the return value just needs to be passed to
 * SEC_PKCS7Encode() or to SEC_PKCS7EncoderStart() to create the encoded data,
 * and finally to SEC_PKCS7DestroyContentInfo().
 *
 * An error results in a return value of NULL and an error set.
 * (Retrieve specific errors via PORT_GetError()/XP_GetError().)
 */
NSSCMSMessage *
NSS_SMIMEMessage_CreateEncrypted(CERTCertificate *scert,
                        CERTCertificate **rcerts,
                        CERTCertDBHandle *certdb,
                        PK11PasswordFunc pwfn,
                        void *pwfn_arg)
{
    NSSCMSMessage *cmsg;
    long cipher;
    SECOidTag encalg;
    int keysize;
    int mapi, rci;

    cipher = smime_choose_cipher (scert, rcerts);
    if (cipher < 0)
        return NULL;

    mapi = smime_mapi_by_cipher (cipher);
    if (mapi < 0)
        return NULL;

    /*
     * XXX This is stretching it -- CreateEnvelopedData should probably
     * take a cipher itself of some sort, because we cannot know what the
     * future will bring in terms of parameters for each type of algorithm.
     * For example, just an algorithm and keysize is *not* sufficient to
     * fully specify the usage of RC5 (which also needs to know rounds and
     * block size).  Work this out into a better API!
     */
    encalg = smime_cipher_map[mapi].algtag;
    keysize = smime_keysize_by_cipher (cipher);
    if (keysize < 0)
        return NULL;

    cinfo = SEC_PKCS7CreateEnvelopedData (scert, certUsageEmailRecipient,
                                          certdb, encalg, keysize,
                                          pwfn, pwfn_arg);
    if (cinfo == NULL)
        return NULL;

    for (rci = 0; rcerts[rci] != NULL; rci++) {
        if (rcerts[rci] == scert)
            continue;
        if (SEC_PKCS7AddRecipient (cinfo, rcerts[rci], certUsageEmailRecipient,
                                   NULL) != SECSuccess) {
            SEC_PKCS7DestroyContentInfo (cinfo);
            return NULL;
        }
    }

    return cinfo;
}


/*
 * Start an S/MIME signing context.
 *
 * "scert" is the cert that will be used to sign the data.  It will be
 * checked for validity.
 *
 * "ecert" is the signer's encryption cert.  If it is different from
 * scert, then it will be included in the signed message so that the
 * recipient can save it for future encryptions.
 *
 * "certdb" is the cert database to use for verifying the cert.
 * It can be NULL if a default database is available (like in the client).
 *
 * "digestalg" names the digest algorithm (e.g. SEC_OID_SHA1).
 * XXX There should be SECMIME functions for hashing, or the hashing should
 * be built into this interface, which we would like because we would
 * support more smartcards that way, and then this argument should go away.)
 *
 * "digest" is the actual digest of the data.  It must be provided in
 * the case of detached data or NULL if the content will be included.
 *
 * This function already does all of the stuff specific to S/MIME protocol
 * and local policy; the return value just needs to be passed to
 * SEC_PKCS7Encode() or to SEC_PKCS7EncoderStart() to create the encoded data,
 * and finally to SEC_PKCS7DestroyContentInfo().
 *
 * An error results in a return value of NULL and an error set.
 * (Retrieve specific errors via PORT_GetError()/XP_GetError().)
 */

NSSCMSMessage *
NSS_SMIMEMessage_CreateSigned(CERTCertificate *scert,
                      CERTCertificate *ecert,
                      CERTCertDBHandle *certdb,
                      SECOidTag digestalgtag,
                      SECItem *digest,
                      PK11PasswordFunc pwfn,
                      void *pwfn_arg)
{
    NSSCMSMessage *cmsg;
    NSSCMSSignedData *sigd;
    NSSCMSSignerInfo *signerinfo;

    /* See note in header comment above about digestalg. */
    /* Doesn't explain this.  PORT_Assert (digestalgtag == SEC_OID_SHA1); */

    cmsg = NSS_CMSMessage_Create(NULL);
    if (cmsg == NULL)
        return NULL;

    sigd = NSS_CMSSignedData_Create(cmsg);
    if (sigd == NULL)
        goto loser;

    /* create just one signerinfo */
    signerinfo = NSS_CMSSignerInfo_Create(cmsg, scert, digestalgtag);
    if (signerinfo == NULL)
        goto loser;

    /* Add the signing time to the signerinfo.  */
    if (NSS_CMSSignerInfo_AddSigningTime(signerinfo, PR_Now()) != SECSuccess)
        goto loser;

    /* and add the SMIME profile */
    if (NSS_SMIMESignerInfo_AddSMIMEProfile(signerinfo, scert) != SECSuccess)
        goto loser;

    /* now add the signerinfo to the signeddata */
    if (NSS_CMSSignedData_AddSignerInfo(sigd, signerinfo) != SECSuccess)
        goto loser;

    /* include the signing cert and its entire chain */
    /* note that there are no checks for duplicate certs in place, as all the */
    /* essential data structures (like set of certificate) are not there */
    if (NSS_CMSSignedData_AddCertChain(sigd, scert) != SECSuccess)
        goto loser;

    /* If the encryption cert and the signing cert differ, then include
     * the encryption cert too. */
    if ( ( ecert != NULL ) && ( ecert != scert ) ) {
        if (NSS_CMSSignedData_AddCertificate(sigd, ecert) != SECSuccess)
            goto loser;
    }

    return cmsg;
loser:
    if (cmsg)
        NSS_CMSMessage_Destroy(cmsg);
    return NULL;
}
#endif
