2 * The contents of this file are subject to the Mozilla Public
3 * License Version 1.1 (the "License"); you may not use this file
4 * except in compliance with the License. You may obtain a copy of
5 * the License at http://www.mozilla.org/MPL/
7 * Software distributed under the License is distributed on an "AS
8 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9 * implied. See the License for the specific language governing
10 * rights and limitations under the License.
12 * The Original Code is the Netscape security libraries.
14 * The Initial Developer of the Original Code is Netscape
15 * Communications Corporation. Portions created by Netscape are
16 * Copyright (C) 1994-2000 Netscape Communications Corporation. All
21 * Alternatively, the contents of this file may be used under the
22 * terms of the GNU General Public License Version 2 or later (the
23 * "GPL"), in which case the provisions of the GPL are applicable
24 * instead of those above. If you wish to allow use of your
25 * version of this file only under the terms of the GPL and not to
26 * allow others to use your version of this file under the MPL,
27 * indicate your decision by deleting the provisions above and
28 * replace them with the notice and other provisions required by
29 * the GPL. If you do not delete the provisions above, a recipient
30 * may use your version of this file under either the MPL or the
35 * CMS recipientInfo methods.
41 #include "SecAsn1Item.h"
44 #include <security_asn1/secasn1.h>
45 #include <security_asn1/secerr.h>
46 #include <security_asn1/secport.h>
48 #include <Security/SecKeyPriv.h>
49 #include <Security/SecCertificatePriv.h>
50 #include <Security/SecCertificateInternal.h>
52 #include "SecCmsRecipientInfo.h"
55 nss_cmsrecipientinfo_usessubjectkeyid(SecCmsRecipientInfoRef ri
)
57 if (ri
->recipientInfoType
== SecCmsRecipientInfoIDKeyTrans
) {
58 SecCmsRecipientIdentifier
*rid
;
59 rid
= &ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
;
60 if (rid
->identifierType
== SecCmsRecipientIDSubjectKeyID
) {
68 static SecCmsRecipientInfoRef
69 nss_cmsrecipientinfo_create(SecCmsEnvelopedDataRef envd
, SecCmsRecipientIDSelector type
,
70 SecCertificateRef cert
, SecPublicKeyRef pubKey
,
71 const SecAsn1Item
*subjKeyID
)
73 SecCmsRecipientInfoRef ri
;
76 OSStatus rv
= SECSuccess
;
77 SecCmsRecipientEncryptedKey
*rek
;
78 SecCmsOriginatorIdentifierOrKey
*oiok
;
79 unsigned long version
;
82 const SECAlgorithmID
*algid
;
83 SECAlgorithmID freeAlgID
;
85 SecCmsRecipientIdentifier
*rid
;
87 poolp
= envd
->contentInfo
.cmsg
->poolp
;
89 mark
= PORT_ArenaMark(poolp
);
91 ri
= (SecCmsRecipientInfoRef
)PORT_ArenaZAlloc(poolp
, sizeof(SecCmsRecipientInfo
));
95 ri
->envelopedData
= envd
;
98 if (type
== SecCmsRecipientIDIssuerSN
)
100 rv
= SecCertificateGetAlgorithmID(cert
,&algid
);
103 rv
= SecKeyGetAlgorithmID(pubKey
,&algid
);
106 ri
->cert
= CERT_DupCertificate(cert
);
107 if (ri
->cert
== NULL
)
110 const SecAsn1AlgId
*length_data_swapped
= (const SecAsn1AlgId
*)SecCertificateGetPublicKeyAlgorithm(cert
);
111 freeAlgID
.algorithm
.Length
= (size_t)length_data_swapped
->algorithm
.Data
;
112 freeAlgID
.algorithm
.Data
= (uint8_t *)length_data_swapped
->algorithm
.Length
;
113 freeAlgID
.parameters
.Length
= (size_t)length_data_swapped
->parameters
.Data
;
114 freeAlgID
.parameters
.Data
= (uint8_t *)length_data_swapped
->parameters
.Length
;
118 certalgtag
= SECOID_GetAlgorithmTag(algid
);
120 rid
= &ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
;
121 switch (certalgtag
) {
122 case SEC_OID_PKCS1_RSA_ENCRYPTION
:
123 ri
->recipientInfoType
= SecCmsRecipientInfoIDKeyTrans
;
124 rid
->identifierType
= type
;
125 if (type
== SecCmsRecipientIDIssuerSN
) {
126 rid
->id
.issuerAndSN
= CERT_GetCertIssuerAndSN(poolp
, cert
);
127 if (rid
->id
.issuerAndSN
== NULL
) {
130 } else if (type
== SecCmsRecipientIDSubjectKeyID
){
132 rid
->id
.subjectKeyID
= PORT_ArenaNew(poolp
, SecAsn1Item
);
133 if (rid
->id
.subjectKeyID
== NULL
) {
135 PORT_SetError(SEC_ERROR_NO_MEMORY
);
138 SECITEM_CopyItem(poolp
, rid
->id
.subjectKeyID
, subjKeyID
);
139 if (rid
->id
.subjectKeyID
->Data
== NULL
) {
141 PORT_SetError(SEC_ERROR_NO_MEMORY
);
146 SecCmsKeyTransRecipientInfoEx
*riExtra
;
147 riExtra
= &ri
->ri
.keyTransRecipientInfoEx
;
148 riExtra
->version
= 0;
149 riExtra
->pubKey
= SECKEY_CopyPublicKey(pubKey
);
150 if (riExtra
->pubKey
== NULL
) {
152 PORT_SetError(SEC_ERROR_NO_MEMORY
);
157 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
161 case SEC_OID_MISSI_KEA_DSS_OLD
:
162 case SEC_OID_MISSI_KEA_DSS
:
163 case SEC_OID_MISSI_KEA
:
164 PORT_Assert(type
!= SecCmsRecipientIDSubjectKeyID
);
165 if (type
== SecCmsRecipientIDSubjectKeyID
) {
169 /* backward compatibility - this is not really a keytrans operation */
170 ri
->recipientInfoType
= SecCmsRecipientInfoIDKeyTrans
;
171 /* hardcoded issuerSN choice for now */
172 ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
.identifierType
= SecCmsRecipientIDIssuerSN
;
173 ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
.id
.issuerAndSN
= CERT_GetCertIssuerAndSN(poolp
, cert
);
174 if (ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
.id
.issuerAndSN
== NULL
) {
179 case SEC_OID_X942_DIFFIE_HELMAN_KEY
: /* dh-public-number */
180 PORT_Assert(type
!= SecCmsRecipientIDSubjectKeyID
);
181 if (type
== SecCmsRecipientIDSubjectKeyID
) {
185 /* a key agreement op */
186 ri
->recipientInfoType
= SecCmsRecipientInfoIDKeyAgree
;
188 if (ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
.id
.issuerAndSN
== NULL
) {
192 /* we do not support the case where multiple recipients
193 * share the same KeyAgreeRecipientInfo and have multiple RecipientEncryptedKeys
194 * in this case, we would need to walk all the recipientInfos, take the
195 * ones that do KeyAgreement algorithms and join them, algorithm by algorithm
196 * Then, we'd generate ONE ukm and OriginatorIdentifierOrKey */
198 /* only epheremal-static Diffie-Hellman is supported for now
199 * this is the only form of key agreement that provides potential anonymity
200 * of the sender, plus we do not have to include certs in the message */
202 /* force single recipientEncryptedKey for now */
203 if ((rek
= SecCmsRecipientEncryptedKeyCreate(poolp
)) == NULL
) {
208 /* hardcoded IssuerSN choice for now */
209 rek
->recipientIdentifier
.identifierType
= SecCmsKeyAgreeRecipientIDIssuerSN
;
210 if ((rek
->recipientIdentifier
.id
.issuerAndSN
= CERT_GetCertIssuerAndSN(poolp
, cert
)) == NULL
) {
215 oiok
= &(ri
->ri
.keyAgreeRecipientInfo
.originatorIdentifierOrKey
);
217 /* see RFC2630 12.3.1.1 */
218 oiok
->identifierType
= SecCmsOriginatorIDOrKeyOriginatorPublicKey
;
220 rv
= SecCmsArrayAdd(poolp
, (void ***)&ri
->ri
.keyAgreeRecipientInfo
.recipientEncryptedKeys
,
225 /* other algorithms not supported yet */
226 /* NOTE that we do not support any KEK algorithm */
227 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM
);
232 if (rv
== SECFailure
)
236 switch (ri
->recipientInfoType
) {
237 case SecCmsRecipientInfoIDKeyTrans
:
238 if (ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
.identifierType
== SecCmsRecipientIDIssuerSN
)
239 version
= SEC_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_ISSUERSN
;
241 version
= SEC_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_SUBJKEY
;
242 dummy
= SEC_ASN1EncodeInteger(poolp
, &(ri
->ri
.keyTransRecipientInfo
.version
), version
);
246 case SecCmsRecipientInfoIDKeyAgree
:
247 dummy
= SEC_ASN1EncodeInteger(poolp
, &(ri
->ri
.keyAgreeRecipientInfo
.version
),
248 SEC_CMS_KEYAGREE_RECIPIENT_INFO_VERSION
);
252 case SecCmsRecipientInfoIDKEK
:
253 /* NOTE: this cannot happen as long as we do not support any KEK algorithm */
254 dummy
= SEC_ASN1EncodeInteger(poolp
, &(ri
->ri
.kekRecipientInfo
.version
),
255 SEC_CMS_KEK_RECIPIENT_INFO_VERSION
);
262 if (SecCmsEnvelopedDataAddRecipient(envd
, ri
))
265 PORT_ArenaUnmark (poolp
, mark
);
268 SECKEY_DestroySubjectPublicKeyInfo(freeSpki
);
275 SECKEY_DestroySubjectPublicKeyInfo(freeSpki
);
277 PORT_ArenaRelease (poolp
, mark
);
282 * SecCmsRecipientInfoCreate - create a recipientinfo
284 * we currently do not create KeyAgreement recipientinfos with multiple
285 * recipientEncryptedKeys the certificate is supposed to have been
286 * verified by the caller
288 SecCmsRecipientInfoRef
289 SecCmsRecipientInfoCreate(SecCmsEnvelopedDataRef envd
, SecCertificateRef cert
)
291 /* TODO: we might want to prefer subjkeyid */
293 SecCmsRecipientInfoRef info
= SecCmsRecipientInfoCreateWithSubjKeyIDFromCert(envd
, cert
);
299 return nss_cmsrecipientinfo_create(envd
, SecCmsRecipientIDIssuerSN
, cert
,
303 SecCmsRecipientInfoRef
304 SecCmsRecipientInfoCreateWithSubjKeyID(SecCmsEnvelopedDataRef envd
,
305 const SecAsn1Item
* subjKeyID
,
306 SecPublicKeyRef pubKey
)
308 return nss_cmsrecipientinfo_create(envd
, SecCmsRecipientIDSubjectKeyID
,
309 NULL
, pubKey
, subjKeyID
);
313 SecCmsRecipientInfoRef
314 SecCmsRecipientInfoCreateWithSubjKeyIDFromCert(SecCmsEnvelopedDataRef envd
,
315 SecCertificateRef cert
)
317 SecPublicKeyRef pubKey
= NULL
;
318 SecAsn1Item subjKeyID
= {0, NULL
};
319 SecCmsRecipientInfoRef retVal
= NULL
;
321 if (!envd
|| !cert
) {
324 pubKey
= CERT_ExtractPublicKey(cert
);
328 if (CERT_FindSubjectKeyIDExtension(cert
, &subjKeyID
) != SECSuccess
||
329 subjKeyID
.Data
== NULL
) {
332 retVal
= SecCmsRecipientInfoCreateWithSubjKeyID(envd
, &subjKeyID
, pubKey
);
335 SECKEY_DestroyPublicKey(pubKey
);
338 SECITEM_FreeItem(&subjKeyID
, PR_FALSE
);
343 SecCmsRecipientInfoRef
344 SecCmsRecipientInfoCreateWithSubjKeyIDFromCert(SecCmsEnvelopedDataRef envd
,
345 SecCertificateRef cert
)
347 SecPublicKeyRef pubKey
= NULL
;
348 SecAsn1Item subjKeyID
= {0, NULL
};
349 SecCmsRecipientInfoRef retVal
= NULL
;
350 CFDataRef subjectKeyIDData
= NULL
;
352 if (!envd
|| !cert
) {
355 subjectKeyIDData
= SecCertificateGetSubjectKeyID(cert
);
356 if (!subjectKeyIDData
)
359 CFDataGetLength(subjectKeyIDData
);
360 subjKeyID
.Data
= (uint8_t *)CFDataGetBytePtr(subjectKeyIDData
);
361 retVal
= nss_cmsrecipientinfo_create(envd
, SecCmsRecipientIDSubjectKeyID
,
362 cert
, pubKey
, &subjKeyID
);
371 SecCmsRecipientInfoDestroy(SecCmsRecipientInfoRef ri
)
373 /* version was allocated on the pool, so no need to destroy it */
374 /* issuerAndSN was allocated on the pool, so no need to destroy it */
375 if (ri
->cert
!= NULL
)
376 CERT_DestroyCertificate(ri
->cert
);
378 if (nss_cmsrecipientinfo_usessubjectkeyid(ri
)) {
379 SecCmsKeyTransRecipientInfoEx
*extra
;
380 extra
= &ri
->ri
.keyTransRecipientInfoEx
;
382 SECKEY_DestroyPublicKey(extra
->pubKey
);
385 /* recipientInfo structure itself was allocated on the pool, so no need to destroy it */
390 SecCmsRecipientInfoGetVersion(SecCmsRecipientInfoRef ri
)
392 unsigned long version
;
393 SecAsn1Item
* versionitem
= NULL
;
395 switch (ri
->recipientInfoType
) {
396 case SecCmsRecipientInfoIDKeyTrans
:
397 /* ignore subIndex */
398 versionitem
= &(ri
->ri
.keyTransRecipientInfo
.version
);
400 case SecCmsRecipientInfoIDKEK
:
401 /* ignore subIndex */
402 versionitem
= &(ri
->ri
.kekRecipientInfo
.version
);
404 case SecCmsRecipientInfoIDKeyAgree
:
405 versionitem
= &(ri
->ri
.keyAgreeRecipientInfo
.version
);
409 PORT_Assert(versionitem
);
410 if (versionitem
== NULL
)
413 /* always take apart the SecAsn1Item */
414 if (SEC_ASN1DecodeInteger(versionitem
, &version
) != SECSuccess
)
421 SecCmsRecipientInfoGetEncryptedKey(SecCmsRecipientInfoRef ri
, int subIndex
)
423 SecAsn1Item
* enckey
= NULL
;
425 switch (ri
->recipientInfoType
) {
426 case SecCmsRecipientInfoIDKeyTrans
:
427 /* ignore subIndex */
428 enckey
= &(ri
->ri
.keyTransRecipientInfo
.encKey
);
430 case SecCmsRecipientInfoIDKEK
:
431 /* ignore subIndex */
432 enckey
= &(ri
->ri
.kekRecipientInfo
.encKey
);
434 case SecCmsRecipientInfoIDKeyAgree
:
435 enckey
= &(ri
->ri
.keyAgreeRecipientInfo
.recipientEncryptedKeys
[subIndex
]->encKey
);
443 SecCmsRecipientInfoGetKeyEncryptionAlgorithmTag(SecCmsRecipientInfoRef ri
)
445 SECOidTag encalgtag
= SEC_OID_UNKNOWN
; /* an invalid encryption alg */
447 switch (ri
->recipientInfoType
) {
448 case SecCmsRecipientInfoIDKeyTrans
:
449 encalgtag
= SECOID_GetAlgorithmTag(&(ri
->ri
.keyTransRecipientInfo
.keyEncAlg
));
451 case SecCmsRecipientInfoIDKeyAgree
:
452 encalgtag
= SECOID_GetAlgorithmTag(&(ri
->ri
.keyAgreeRecipientInfo
.keyEncAlg
));
454 case SecCmsRecipientInfoIDKEK
:
455 encalgtag
= SECOID_GetAlgorithmTag(&(ri
->ri
.kekRecipientInfo
.keyEncAlg
));
462 SecCmsRecipientInfoWrapBulkKey(SecCmsRecipientInfoRef ri
, SecSymmetricKeyRef bulkkey
,
463 SECOidTag bulkalgtag
)
465 SecCertificateRef cert
;
466 SECOidTag certalgtag
;
467 OSStatus rv
= SECSuccess
;
469 SecAsn1Item
* params
= NULL
;
470 SecCmsRecipientEncryptedKey
*rek
;
471 SecCmsOriginatorIdentifierOrKey
*oiok
;
473 const SECAlgorithmID
*algid
;
475 SecCmsKeyTransRecipientInfoEx
*extra
= NULL
;
476 Boolean usesSubjKeyID
;
478 poolp
= ri
->envelopedData
->contentInfo
.cmsg
->poolp
;
480 usesSubjKeyID
= nss_cmsrecipientinfo_usessubjectkeyid(ri
);
483 rv
= SecCertificateGetAlgorithmID(cert
,&algid
);
487 SECAlgorithmID freeAlgID
;
488 const SecAsn1AlgId
*length_data_swapped
= (const SecAsn1AlgId
*)SecCertificateGetPublicKeyAlgorithm(cert
);
489 freeAlgID
.algorithm
.Length
= (size_t)length_data_swapped
->algorithm
.Data
;
490 freeAlgID
.algorithm
.Data
= (uint8_t *)length_data_swapped
->algorithm
.Length
;
491 freeAlgID
.parameters
.Length
= (size_t)length_data_swapped
->parameters
.Data
;
492 freeAlgID
.parameters
.Data
= (uint8_t *)length_data_swapped
->parameters
.Length
;
495 } else if (usesSubjKeyID
) {
496 extra
= &ri
->ri
.keyTransRecipientInfoEx
;
498 PORT_Assert(extra
->pubKey
);
499 if (!extra
->pubKey
) {
500 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
504 rv
= SecKeyGetAlgorithmID(extra
->pubKey
,&algid
);
508 certalgtag
= SECOID_GetAlgorithmTag(algid
);
510 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
514 /* XXX set ri->recipientInfoType to the proper value here */
515 /* or should we look if it's been set already ? */
517 certalgtag
= SECOID_GetAlgorithmTag(algid
);
518 switch (certalgtag
) {
519 case SEC_OID_PKCS1_RSA_ENCRYPTION
:
520 /* wrap the symkey */
522 rv
= SecCmsUtilEncryptSymKeyRSA(poolp
, cert
, bulkkey
,
523 &ri
->ri
.keyTransRecipientInfo
.encKey
);
524 if (rv
!= SECSuccess
)
526 } else if (usesSubjKeyID
) {
527 PORT_Assert(extra
!= NULL
);
528 rv
= SecCmsUtilEncryptSymKeyRSAPubKey(poolp
, extra
->pubKey
,
529 bulkkey
, &ri
->ri
.keyTransRecipientInfo
.encKey
);
530 if (rv
!= SECSuccess
)
534 rv
= SECOID_SetAlgorithmID(poolp
, &(ri
->ri
.keyTransRecipientInfo
.keyEncAlg
), certalgtag
, NULL
);
537 case SEC_OID_MISSI_KEA_DSS_OLD
:
538 case SEC_OID_MISSI_KEA_DSS
:
539 case SEC_OID_MISSI_KEA
:
540 rv
= SecCmsUtilEncryptSymKeyMISSI(poolp
, cert
, bulkkey
,
542 &ri
->ri
.keyTransRecipientInfo
.encKey
,
543 ¶ms
, ri
->cmsg
->pwfn_arg
);
544 if (rv
!= SECSuccess
)
547 /* here, we DO need to pass the params to the wrap function because, with
548 * RSA, there is no funny stuff going on with generation of IV vectors or so */
549 rv
= SECOID_SetAlgorithmID(poolp
, &(ri
->ri
.keyTransRecipientInfo
.keyEncAlg
), certalgtag
, params
);
551 case SEC_OID_X942_DIFFIE_HELMAN_KEY
: /* dh-public-number */
552 rek
= ri
->ri
.keyAgreeRecipientInfo
.recipientEncryptedKeys
[0];
558 oiok
= &(ri
->ri
.keyAgreeRecipientInfo
.originatorIdentifierOrKey
);
559 PORT_Assert(oiok
->identifierType
== SecCmsOriginatorIDOrKeyOriginatorPublicKey
);
561 /* see RFC2630 12.3.1.1 */
562 if (SECOID_SetAlgorithmID(poolp
, &oiok
->id
.originatorPublicKey
.algorithmIdentifier
,
563 SEC_OID_X942_DIFFIE_HELMAN_KEY
, NULL
) != SECSuccess
) {
568 /* this will generate a key pair, compute the shared secret, */
569 /* derive a key and ukm for the keyEncAlg out of it, encrypt the bulk key with */
570 /* the keyEncAlg, set encKey, keyEncAlg, publicKey etc. */
571 rv
= SecCmsUtilEncryptSymKeyESDH(poolp
, cert
, bulkkey
,
573 &ri
->ri
.keyAgreeRecipientInfo
.ukm
,
574 &ri
->ri
.keyAgreeRecipientInfo
.keyEncAlg
,
575 &oiok
->id
.originatorPublicKey
.publicKey
);
580 /* other algorithms not supported yet */
581 /* NOTE that we do not support any KEK algorithm */
582 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM
);
588 SECKEY_DestroySubjectPublicKeyInfo(freeSpki
);
595 SecCmsRecipientInfoUnwrapBulkKey(SecCmsRecipientInfoRef ri
, int subIndex
,
596 SecCertificateRef cert
, SecPrivateKeyRef privkey
, SECOidTag bulkalgtag
)
598 SecSymmetricKeyRef bulkkey
= NULL
;
599 SECAlgorithmID
*encalg
;
601 SecAsn1Item
* enckey
;
604 ri
->cert
= CERT_DupCertificate(cert
);
605 /* mark the recipientInfo so we can find it later */
607 switch (ri
->recipientInfoType
) {
608 case SecCmsRecipientInfoIDKeyTrans
:
609 encalg
= &(ri
->ri
.keyTransRecipientInfo
.keyEncAlg
);
610 encalgtag
= SECOID_GetAlgorithmTag(&(ri
->ri
.keyTransRecipientInfo
.keyEncAlg
));
611 enckey
= &(ri
->ri
.keyTransRecipientInfo
.encKey
); /* ignore subIndex */
613 case SEC_OID_PKCS1_RSA_ENCRYPTION
:
614 /* RSA encryption algorithm: */
615 /* get the symmetric (bulk) key by unwrapping it using our private key */
616 bulkkey
= SecCmsUtilDecryptSymKeyRSA(privkey
, enckey
, bulkalgtag
);
619 case SEC_OID_NETSCAPE_SMIME_KEA
:
620 /* FORTEZZA key exchange algorithm */
621 /* the supplemental data is in the parameters of encalg */
622 bulkkey
= SecCmsUtilDecryptSymKeyMISSI(privkey
, enckey
, encalg
, bulkalgtag
, ri
->cmsg
->pwfn_arg
);
626 error
= SEC_ERROR_UNSUPPORTED_KEYALG
;
630 case SecCmsRecipientInfoIDKeyAgree
:
631 encalg
= &(ri
->ri
.keyAgreeRecipientInfo
.keyEncAlg
);
632 encalgtag
= SECOID_GetAlgorithmTag(&(ri
->ri
.keyAgreeRecipientInfo
.keyEncAlg
));
633 enckey
= &(ri
->ri
.keyAgreeRecipientInfo
.recipientEncryptedKeys
[subIndex
]->encKey
);
635 case SEC_OID_X942_DIFFIE_HELMAN_KEY
:
636 /* Diffie-Helman key exchange */
637 /* XXX not yet implemented */
638 /* XXX problem: SEC_OID_X942_DIFFIE_HELMAN_KEY points to a PKCS3 mechanism! */
639 /* we support ephemeral-static DH only, so if the recipientinfo */
640 /* has originator stuff in it, we punt (or do we? shouldn't be that hard...) */
641 /* first, we derive the KEK (a symkey!) using a Derive operation, then we get the */
642 /* content encryption key using a Unwrap op */
643 /* the derive operation has to generate the key using the algorithm in RFC2631 */
644 error
= SEC_ERROR_UNSUPPORTED_KEYALG
;
647 error
= SEC_ERROR_UNSUPPORTED_KEYALG
;
651 case SecCmsRecipientInfoIDKEK
:
652 encalg
= &(ri
->ri
.kekRecipientInfo
.keyEncAlg
);
653 encalgtag
= SECOID_GetAlgorithmTag(&(ri
->ri
.kekRecipientInfo
.keyEncAlg
));
654 enckey
= &(ri
->ri
.kekRecipientInfo
.encKey
);
655 /* not supported yet */
656 error
= SEC_ERROR_UNSUPPORTED_KEYALG
;
660 /* XXXX continue here */