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; }
/* * NSS_CMSSignedData_CreateCertsOnly - create a certs-only SignedData. * * cert - base certificates that will be included * include_chain - if true, include the complete cert chain for cert * * More certs and chains can be added via AddCertificate and AddCertChain. * * An error results in a return value of NULL and an error set. * * XXXX CRLs */ NSSCMSSignedData * NSS_CMSSignedData_CreateCertsOnly(NSSCMSMessage *cmsg, CERTCertificate *cert, PRBool include_chain) { NSSCMSSignedData *sigd; void *mark; PLArenaPool *poolp; SECStatus rv; if (!cmsg || !cert) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return NULL; } poolp = cmsg->poolp; mark = PORT_ArenaMark(poolp); sigd = NSS_CMSSignedData_Create(cmsg); if (sigd == NULL) goto loser; /* no signerinfos, thus no digestAlgorithms */ /* but certs */ if (include_chain) { rv = NSS_CMSSignedData_AddCertChain(sigd, cert); } else { rv = NSS_CMSSignedData_AddCertificate(sigd, cert); } if (rv != SECSuccess) goto loser; /* RFC2630 5.2 sez: * In the degenerate case where there are no signers, the * EncapsulatedContentInfo value being "signed" is irrelevant. In this * case, the content type within the EncapsulatedContentInfo value being * "signed" should be id-data (as defined in section 4), and the content * field of the EncapsulatedContentInfo value should be omitted. */ rv = NSS_CMSContentInfo_SetContent_Data(cmsg, &(sigd->contentInfo), NULL, PR_TRUE); if (rv != SECSuccess) goto loser; PORT_ArenaUnmark(poolp, mark); return sigd; loser: if (sigd) NSS_CMSSignedData_Destroy(sigd); PORT_ArenaRelease(poolp, mark); return NULL; }