/* * 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().) */ SEC_PKCS7ContentInfo * SECMIME_CreateEncrypted(CERTCertificate *scert, CERTCertificate **rcerts, CERTCertDBHandle *certdb, SECKEYGetPasswordKey pwfn, void *pwfn_arg) { SEC_PKCS7ContentInfo *cinfo; 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_maps[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; }
/* * NSS_SMIMEUtil_FindBulkAlgForRecipients - find bulk algorithm suitable for all recipients * * it would be great for UI purposes if there would be a way to find out which recipients * prevented a strong cipher from being used... */ SECStatus NSS_SMIMEUtil_FindBulkAlgForRecipients(CERTCertificate **rcerts, SECOidTag *bulkalgtag, int *keysize) { unsigned long cipher; int mapi; cipher = smime_choose_cipher(NULL, rcerts); mapi = smime_mapi_by_cipher(cipher); *bulkalgtag = smime_cipher_map[mapi].algtag; *keysize = smime_keysize_by_cipher(smime_cipher_map[mapi].cipher); return SECSuccess; }
/* * SecSMIMEFindBulkAlgForRecipients - find bulk algorithm suitable for all recipients * * it would be great for UI purposes if there would be a way to find out which recipients * prevented a strong cipher from being used... */ OSStatus SecSMIMEFindBulkAlgForRecipients(SecCertificateRef *rcerts, SECOidTag *bulkalgtag, int *keysize) { unsigned long cipher; int mapi; cipher = smime_choose_cipher(NULL, rcerts); mapi = smime_mapi_by_cipher(cipher); if (mapi < 0) { return SECFailure; } *bulkalgtag = smime_cipher_map[mapi].algtag; *keysize = smime_keysize_by_cipher(smime_cipher_map[mapi].cipher); return SECSuccess; }