SecSymmetricKeyRef SecCmsRecipientInfoUnwrapBulkKey(SecCmsRecipientInfoRef ri, int subIndex, SecCertificateRef cert, SecPrivateKeyRef privkey, SECOidTag bulkalgtag) { SecSymmetricKeyRef bulkkey = NULL; SECAlgorithmID *encalg; SECOidTag encalgtag; SecAsn1Item * enckey; int error; ri->cert = CERT_DupCertificate(cert); /* mark the recipientInfo so we can find it later */ switch (ri->recipientInfoType) { case SecCmsRecipientInfoIDKeyTrans: encalg = &(ri->ri.keyTransRecipientInfo.keyEncAlg); encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.keyTransRecipientInfo.keyEncAlg)); enckey = &(ri->ri.keyTransRecipientInfo.encKey); /* ignore subIndex */ switch (encalgtag) { case SEC_OID_PKCS1_RSA_ENCRYPTION: /* RSA encryption algorithm: */ /* get the symmetric (bulk) key by unwrapping it using our private key */ bulkkey = SecCmsUtilDecryptSymKeyRSA(privkey, enckey, bulkalgtag); break; #if 0 case SEC_OID_NETSCAPE_SMIME_KEA: /* FORTEZZA key exchange algorithm */ /* the supplemental data is in the parameters of encalg */ bulkkey = SecCmsUtilDecryptSymKeyMISSI(privkey, enckey, encalg, bulkalgtag, ri->cmsg->pwfn_arg); break; #endif /* 0 */ default: error = SEC_ERROR_UNSUPPORTED_KEYALG; goto loser; } break; case SecCmsRecipientInfoIDKeyAgree: encalg = &(ri->ri.keyAgreeRecipientInfo.keyEncAlg); encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.keyAgreeRecipientInfo.keyEncAlg)); enckey = &(ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[subIndex]->encKey); switch (encalgtag) { case SEC_OID_X942_DIFFIE_HELMAN_KEY: /* Diffie-Helman key exchange */ /* XXX not yet implemented */ /* XXX problem: SEC_OID_X942_DIFFIE_HELMAN_KEY points to a PKCS3 mechanism! */ /* we support ephemeral-static DH only, so if the recipientinfo */ /* has originator stuff in it, we punt (or do we? shouldn't be that hard...) */ /* first, we derive the KEK (a symkey!) using a Derive operation, then we get the */ /* content encryption key using a Unwrap op */ /* the derive operation has to generate the key using the algorithm in RFC2631 */ error = SEC_ERROR_UNSUPPORTED_KEYALG; break; default: error = SEC_ERROR_UNSUPPORTED_KEYALG; goto loser; } break; case SecCmsRecipientInfoIDKEK: encalg = &(ri->ri.kekRecipientInfo.keyEncAlg); encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.kekRecipientInfo.keyEncAlg)); enckey = &(ri->ri.kekRecipientInfo.encKey); /* not supported yet */ error = SEC_ERROR_UNSUPPORTED_KEYALG; goto loser; break; } /* XXXX continue here */ return bulkkey; loser: return NULL; }
SecSymmetricKeyRef SecCmsRecipientInfoUnwrapBulkKey(SecCmsRecipientInfoRef ri, int subIndex, SecCertificateRef cert, SecPrivateKeyRef privkey, SECOidTag bulkalgtag) { SecSymmetricKeyRef bulkkey = NULL; SECAlgorithmID *encalg; SECOidTag encalgtag; CSSM_DATA_PTR enckey; int error; ri->cert = CERT_DupCertificate(cert); /* mark the recipientInfo so we can find it later */ switch (ri->recipientInfoType) { case SecCmsRecipientInfoIDKeyTrans: encalg = &(ri->ri.keyTransRecipientInfo.keyEncAlg); encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.keyTransRecipientInfo.keyEncAlg)); enckey = &(ri->ri.keyTransRecipientInfo.encKey); /* ignore subIndex */ switch (encalgtag) { case SEC_OID_PKCS1_RSA_ENCRYPTION: /* RSA encryption algorithm: */ /* get the symmetric (bulk) key by unwrapping it using our private key */ bulkkey = SecCmsUtilDecryptSymKeyRSA(privkey, enckey, bulkalgtag); break; #if 0 case SEC_OID_NETSCAPE_SMIME_KEA: /* FORTEZZA key exchange algorithm */ /* the supplemental data is in the parameters of encalg */ bulkkey = SecCmsUtilDecryptSymKeyMISSI(privkey, enckey, encalg, bulkalgtag, ri->cmsg->pwfn_arg); break; #endif /* 0 */ default: error = SEC_ERROR_UNSUPPORTED_KEYALG; goto loser; } break; case SecCmsRecipientInfoIDKeyAgree: encalg = &(ri->ri.keyAgreeRecipientInfo.keyEncAlg); encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.keyAgreeRecipientInfo.keyEncAlg)); enckey = &(ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[subIndex]->encKey); switch (encalgtag) { case SEC_OID_X942_DIFFIE_HELMAN_KEY: /* Diffie-Helman key exchange */ /* XXX not yet implemented */ /* XXX problem: SEC_OID_X942_DIFFIE_HELMAN_KEY points to a PKCS3 mechanism! */ /* we support ephemeral-static DH only, so if the recipientinfo */ /* has originator stuff in it, we punt (or do we? shouldn't be that hard...) */ /* first, we derive the KEK (a symkey!) using a Derive operation, then we get the */ /* content encryption key using a Unwrap op */ /* the derive operation has to generate the key using the algorithm in RFC2631 */ error = SEC_ERROR_UNSUPPORTED_KEYALG; break; case SEC_OID_DH_SINGLE_STD_SHA1KDF: { /* ephemeral-static ECDH */ SecCmsKeyAgreeRecipientInfo *kari = &ri->ri.keyAgreeRecipientInfo; SecCmsOriginatorIdentifierOrKey *oiok = &kari->originatorIdentifierOrKey; if(oiok->identifierType != SecCmsOriginatorIDOrKeyOriginatorPublicKey) { dprintf("SEC_OID_EC_PUBLIC_KEY unwrap key: bad oiok.id\n"); goto loser; } SecCmsOriginatorPublicKey *opk = &oiok->id.originatorPublicKey; /* FIXME - verify opk->algorithmIdentifier here? */ CSSM_DATA senderPubKey = opk->publicKey; /* Bit string, convert here */ senderPubKey.Length = (senderPubKey.Length + 7) >> 3; CSSM_DATA_PTR ukm = &kari->ukm; bulkkey = SecCmsUtilDecryptSymKeyECDH(privkey, enckey, ukm, encalg, bulkalgtag, &senderPubKey); break; } default: error = SEC_ERROR_UNSUPPORTED_KEYALG; goto loser; } break; case SecCmsRecipientInfoIDKEK: encalg = &(ri->ri.kekRecipientInfo.keyEncAlg); encalgtag = SECOID_GetAlgorithmTag(&(ri->ri.kekRecipientInfo.keyEncAlg)); enckey = &(ri->ri.kekRecipientInfo.encKey); /* not supported yet */ error = SEC_ERROR_UNSUPPORTED_KEYALG; goto loser; break; } /* XXXX continue here */ return bulkkey; loser: return NULL; }