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
;
97 ri
->cert
= CERT_DupCertificate(cert
);
101 const SecAsn1AlgId
*length_data_swapped
= (const SecAsn1AlgId
*)SecCertificateGetPublicKeyAlgorithm(cert
);
102 freeAlgID
.algorithm
.Length
= (size_t)length_data_swapped
->algorithm
.Data
;
103 freeAlgID
.algorithm
.Data
= (uint8_t *)length_data_swapped
->algorithm
.Length
;
104 freeAlgID
.parameters
.Length
= (size_t)length_data_swapped
->parameters
.Data
;
105 freeAlgID
.parameters
.Data
= (uint8_t *)length_data_swapped
->parameters
.Length
;
108 certalgtag
= SECOID_GetAlgorithmTag(algid
);
110 rid
= &ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
;
111 switch (certalgtag
) {
112 case SEC_OID_PKCS1_RSA_ENCRYPTION
:
113 ri
->recipientInfoType
= SecCmsRecipientInfoIDKeyTrans
;
114 rid
->identifierType
= type
;
115 if (type
== SecCmsRecipientIDIssuerSN
) {
116 rid
->id
.issuerAndSN
= CERT_GetCertIssuerAndSN(poolp
, cert
);
117 if (rid
->id
.issuerAndSN
== NULL
) {
120 } else if (type
== SecCmsRecipientIDSubjectKeyID
){
122 rid
->id
.subjectKeyID
= PORT_ArenaNew(poolp
, SecAsn1Item
);
123 if (rid
->id
.subjectKeyID
== NULL
) {
125 PORT_SetError(SEC_ERROR_NO_MEMORY
);
128 if (SECITEM_CopyItem(poolp
, rid
->id
.subjectKeyID
, subjKeyID
)) {
130 PORT_SetError(SEC_ERROR_UNKNOWN_CERT
);
133 if (rid
->id
.subjectKeyID
->Data
== NULL
) {
135 PORT_SetError(SEC_ERROR_NO_MEMORY
);
139 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
143 case SEC_OID_MISSI_KEA_DSS_OLD
:
144 case SEC_OID_MISSI_KEA_DSS
:
145 case SEC_OID_MISSI_KEA
:
146 PORT_Assert(type
!= SecCmsRecipientIDSubjectKeyID
);
147 if (type
== SecCmsRecipientIDSubjectKeyID
) {
151 /* backward compatibility - this is not really a keytrans operation */
152 ri
->recipientInfoType
= SecCmsRecipientInfoIDKeyTrans
;
153 /* hardcoded issuerSN choice for now */
154 ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
.identifierType
= SecCmsRecipientIDIssuerSN
;
155 ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
.id
.issuerAndSN
= CERT_GetCertIssuerAndSN(poolp
, cert
);
156 if (ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
.id
.issuerAndSN
== NULL
) {
161 case SEC_OID_X942_DIFFIE_HELMAN_KEY
: /* dh-public-number */
162 PORT_Assert(type
!= SecCmsRecipientIDSubjectKeyID
);
163 if (type
== SecCmsRecipientIDSubjectKeyID
) {
167 /* a key agreement op */
168 ri
->recipientInfoType
= SecCmsRecipientInfoIDKeyAgree
;
170 if (ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
.id
.issuerAndSN
== NULL
) {
174 /* we do not support the case where multiple recipients
175 * share the same KeyAgreeRecipientInfo and have multiple RecipientEncryptedKeys
176 * in this case, we would need to walk all the recipientInfos, take the
177 * ones that do KeyAgreement algorithms and join them, algorithm by algorithm
178 * Then, we'd generate ONE ukm and OriginatorIdentifierOrKey */
180 /* only epheremal-static Diffie-Hellman is supported for now
181 * this is the only form of key agreement that provides potential anonymity
182 * of the sender, plus we do not have to include certs in the message */
184 /* force single recipientEncryptedKey for now */
185 if ((rek
= SecCmsRecipientEncryptedKeyCreate(poolp
)) == NULL
) {
190 /* hardcoded IssuerSN choice for now */
191 rek
->recipientIdentifier
.identifierType
= SecCmsKeyAgreeRecipientIDIssuerSN
;
192 if ((rek
->recipientIdentifier
.id
.issuerAndSN
= CERT_GetCertIssuerAndSN(poolp
, cert
)) == NULL
) {
197 oiok
= &(ri
->ri
.keyAgreeRecipientInfo
.originatorIdentifierOrKey
);
199 /* see RFC2630 12.3.1.1 */
200 oiok
->identifierType
= SecCmsOriginatorIDOrKeyOriginatorPublicKey
;
202 rv
= SecCmsArrayAdd(poolp
, (void ***)&ri
->ri
.keyAgreeRecipientInfo
.recipientEncryptedKeys
,
206 case SEC_OID_EC_PUBLIC_KEY
:
207 /* ephemeral-static ECDH - issuerAndSN, OriginatorPublicKey only */
208 PORT_Assert(type
!= SecCmsRecipientIDSubjectKeyID
);
209 if (type
== SecCmsRecipientIDSubjectKeyID
) {
213 /* a key agreement op */
214 ri
->recipientInfoType
= SecCmsRecipientInfoIDKeyAgree
;
215 ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
.id
.issuerAndSN
= CERT_GetCertIssuerAndSN(poolp
, cert
);
216 if (ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
.id
.issuerAndSN
== NULL
) {
220 /* we do not support the case where multiple recipients
221 * share the same KeyAgreeRecipientInfo and have multiple RecipientEncryptedKeys
222 * in this case, we would need to walk all the recipientInfos, take the
223 * ones that do KeyAgreement algorithms and join them, algorithm by algorithm
224 * Then, we'd generate ONE ukm and OriginatorIdentifierOrKey */
226 /* force single recipientEncryptedKey for now */
227 if ((rek
= SecCmsRecipientEncryptedKeyCreate(poolp
)) == NULL
) {
232 /* hardcoded IssuerSN choice for now */
233 rek
->recipientIdentifier
.identifierType
= SecCmsKeyAgreeRecipientIDIssuerSN
;
234 if ((rek
->recipientIdentifier
.id
.issuerAndSN
= CERT_GetCertIssuerAndSN(poolp
, cert
)) == NULL
) {
239 oiok
= &(ri
->ri
.keyAgreeRecipientInfo
.originatorIdentifierOrKey
);
241 /* see RFC 3278 3.1.1 */
242 oiok
->identifierType
= SecCmsOriginatorIDOrKeyOriginatorPublicKey
;
244 rv
= SecCmsArrayAdd(poolp
, (void ***)&ri
->ri
.keyAgreeRecipientInfo
.recipientEncryptedKeys
,
249 /* other algorithms not supported yet */
250 /* NOTE that we do not support any KEK algorithm */
251 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM
);
256 if (rv
== SECFailure
)
260 switch (ri
->recipientInfoType
) {
261 case SecCmsRecipientInfoIDKeyTrans
:
262 if (ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
.identifierType
== SecCmsRecipientIDIssuerSN
)
263 version
= SEC_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_ISSUERSN
;
265 version
= SEC_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_SUBJKEY
;
266 dummy
= SEC_ASN1EncodeInteger(poolp
, &(ri
->ri
.keyTransRecipientInfo
.version
), version
);
270 case SecCmsRecipientInfoIDKeyAgree
:
271 dummy
= SEC_ASN1EncodeInteger(poolp
, &(ri
->ri
.keyAgreeRecipientInfo
.version
),
272 SEC_CMS_KEYAGREE_RECIPIENT_INFO_VERSION
);
276 case SecCmsRecipientInfoIDKEK
:
277 /* NOTE: this cannot happen as long as we do not support any KEK algorithm */
278 dummy
= SEC_ASN1EncodeInteger(poolp
, &(ri
->ri
.kekRecipientInfo
.version
),
279 SEC_CMS_KEK_RECIPIENT_INFO_VERSION
);
286 if (SecCmsEnvelopedDataAddRecipient(envd
, ri
))
289 PORT_ArenaUnmark (poolp
, mark
);
292 SECKEY_DestroySubjectPublicKeyInfo(freeSpki
);
299 SECKEY_DestroySubjectPublicKeyInfo(freeSpki
);
301 PORT_ArenaRelease (poolp
, mark
);
306 * SecCmsRecipientInfoCreate - create a recipientinfo
308 * we currently do not create KeyAgreement recipientinfos with multiple
309 * recipientEncryptedKeys the certificate is supposed to have been
310 * verified by the caller
312 SecCmsRecipientInfoRef
313 SecCmsRecipientInfoCreate(SecCmsEnvelopedDataRef envd
, SecCertificateRef cert
)
315 /* TODO: We might want to prefer subjkeyid */
317 SecCmsRecipientInfoRef info
= SecCmsRecipientInfoCreateWithSubjKeyIDFromCert(envd
, cert
);
323 return nss_cmsrecipientinfo_create(envd
, SecCmsRecipientIDIssuerSN
, cert
,
327 SecCmsRecipientInfoRef
328 SecCmsRecipientInfoCreateWithSubjKeyID(SecCmsEnvelopedDataRef envd
,
329 const SecAsn1Item
* subjKeyID
,
330 SecPublicKeyRef pubKey
)
332 return nss_cmsrecipientinfo_create(envd
, SecCmsRecipientIDSubjectKeyID
,
333 NULL
, pubKey
, subjKeyID
);
336 SecCmsRecipientInfoRef
337 SecCmsRecipientInfoCreateWithSubjKeyIDFromCert(SecCmsEnvelopedDataRef envd
,
338 SecCertificateRef cert
)
340 SecPublicKeyRef pubKey
= NULL
;
341 SecAsn1Item subjKeyID
= {0, NULL
};
342 SecCmsRecipientInfoRef retVal
= NULL
;
343 CFDataRef subjectKeyIDData
= NULL
;
345 if (!envd
|| !cert
) {
348 subjectKeyIDData
= SecCertificateGetSubjectKeyID(cert
);
349 if (!subjectKeyIDData
)
352 CFDataGetLength(subjectKeyIDData
);
353 subjKeyID
.Data
= (uint8_t *)CFDataGetBytePtr(subjectKeyIDData
);
354 retVal
= nss_cmsrecipientinfo_create(envd
, SecCmsRecipientIDSubjectKeyID
,
355 cert
, pubKey
, &subjKeyID
);
363 SecCmsRecipientInfoDestroy(SecCmsRecipientInfoRef ri
)
365 /* version was allocated on the pool, so no need to destroy it */
366 /* issuerAndSN was allocated on the pool, so no need to destroy it */
367 if (ri
->cert
!= NULL
)
368 CERT_DestroyCertificate(ri
->cert
);
370 if (nss_cmsrecipientinfo_usessubjectkeyid(ri
)) {
371 SecCmsKeyTransRecipientInfoEx
*extra
;
372 extra
= &ri
->ri
.keyTransRecipientInfoEx
;
374 SECKEY_DestroyPublicKey(extra
->pubKey
);
377 /* recipientInfo structure itself was allocated on the pool, so no need to destroy it */
382 SecCmsRecipientInfoGetVersion(SecCmsRecipientInfoRef ri
)
384 unsigned long version
;
385 SecAsn1Item
* versionitem
= NULL
;
387 switch (ri
->recipientInfoType
) {
388 case SecCmsRecipientInfoIDKeyTrans
:
389 /* ignore subIndex */
390 versionitem
= &(ri
->ri
.keyTransRecipientInfo
.version
);
392 case SecCmsRecipientInfoIDKEK
:
393 /* ignore subIndex */
394 versionitem
= &(ri
->ri
.kekRecipientInfo
.version
);
396 case SecCmsRecipientInfoIDKeyAgree
:
397 versionitem
= &(ri
->ri
.keyAgreeRecipientInfo
.version
);
401 PORT_Assert(versionitem
);
402 if (versionitem
== NULL
)
405 /* always take apart the SecAsn1Item */
406 if (SEC_ASN1DecodeInteger(versionitem
, &version
) != SECSuccess
)
413 SecCmsRecipientInfoGetEncryptedKey(SecCmsRecipientInfoRef ri
, int subIndex
)
415 SecAsn1Item
* enckey
= NULL
;
417 switch (ri
->recipientInfoType
) {
418 case SecCmsRecipientInfoIDKeyTrans
:
419 /* ignore subIndex */
420 enckey
= &(ri
->ri
.keyTransRecipientInfo
.encKey
);
422 case SecCmsRecipientInfoIDKEK
:
423 /* ignore subIndex */
424 enckey
= &(ri
->ri
.kekRecipientInfo
.encKey
);
426 case SecCmsRecipientInfoIDKeyAgree
:
427 enckey
= &(ri
->ri
.keyAgreeRecipientInfo
.recipientEncryptedKeys
[subIndex
]->encKey
);
435 SecCmsRecipientInfoGetKeyEncryptionAlgorithmTag(SecCmsRecipientInfoRef ri
)
437 SECOidTag encalgtag
= SEC_OID_UNKNOWN
; /* an invalid encryption alg */
439 switch (ri
->recipientInfoType
) {
440 case SecCmsRecipientInfoIDKeyTrans
:
441 encalgtag
= SECOID_GetAlgorithmTag(&(ri
->ri
.keyTransRecipientInfo
.keyEncAlg
));
443 case SecCmsRecipientInfoIDKeyAgree
:
444 encalgtag
= SECOID_GetAlgorithmTag(&(ri
->ri
.keyAgreeRecipientInfo
.keyEncAlg
));
446 case SecCmsRecipientInfoIDKEK
:
447 encalgtag
= SECOID_GetAlgorithmTag(&(ri
->ri
.kekRecipientInfo
.keyEncAlg
));
454 SecCmsRecipientInfoWrapBulkKey(SecCmsRecipientInfoRef ri
, SecSymmetricKeyRef bulkkey
,
455 SECOidTag bulkalgtag
)
457 SecCertificateRef cert
;
458 SECOidTag certalgtag
;
459 OSStatus rv
= SECSuccess
;
460 SecCmsRecipientEncryptedKey
*rek
;
461 SecCmsOriginatorIdentifierOrKey
*oiok
;
462 const SECAlgorithmID
*algid
;
463 SECAlgorithmID freeAlgID
;
465 Boolean usesSubjKeyID
;
466 uint8_t nullData
[2] = {SEC_ASN1_NULL
, 0};
468 SecCmsKeyAgreeRecipientInfo
*kari
;
470 poolp
= ri
->envelopedData
->contentInfo
.cmsg
->poolp
;
472 usesSubjKeyID
= nss_cmsrecipientinfo_usessubjectkeyid(ri
);
474 const SecAsn1AlgId
*length_data_swapped
= (const SecAsn1AlgId
*)SecCertificateGetPublicKeyAlgorithm(cert
);
475 freeAlgID
.algorithm
.Length
= (size_t)length_data_swapped
->algorithm
.Data
;
476 freeAlgID
.algorithm
.Data
= (uint8_t *)length_data_swapped
->algorithm
.Length
;
477 freeAlgID
.parameters
.Length
= (size_t)length_data_swapped
->parameters
.Data
;
478 freeAlgID
.parameters
.Data
= (uint8_t *)length_data_swapped
->parameters
.Length
;
481 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
485 /* XXX set ri->recipientInfoType to the proper value here */
486 /* or should we look if it's been set already ? */
488 certalgtag
= SECOID_GetAlgorithmTag(algid
);
489 switch (certalgtag
) {
490 case SEC_OID_PKCS1_RSA_ENCRYPTION
:
491 /* wrap the symkey */
493 rv
= SecCmsUtilEncryptSymKeyRSA(poolp
, cert
, bulkkey
,
494 &ri
->ri
.keyTransRecipientInfo
.encKey
);
495 if (rv
!= SECSuccess
)
499 rv
= SECOID_SetAlgorithmID(poolp
, &(ri
->ri
.keyTransRecipientInfo
.keyEncAlg
), certalgtag
, NULL
);
501 case SEC_OID_EC_PUBLIC_KEY
:
502 /* These were set up in nss_cmsrecipientinfo_create() */
503 kari
= &ri
->ri
.keyAgreeRecipientInfo
;
504 rek
= kari
->recipientEncryptedKeys
[0];
510 oiok
= &(kari
->originatorIdentifierOrKey
);
511 PORT_Assert(oiok
->identifierType
== SecCmsOriginatorIDOrKeyOriginatorPublicKey
);
514 * RFC 3278 3.1.1 says this AlgId must contain NULL params which is contrary to
515 * any other use of the SEC_OID_EC_PUBLIC_KEY OID. So we provide one
516 * explicitly instead of mucking up the login in SECOID_SetAlgorithmID().
518 nullItem
.Data
= nullData
;
520 if (SECOID_SetAlgorithmID(poolp
, &oiok
->id
.originatorPublicKey
.algorithmIdentifier
,
521 SEC_OID_EC_PUBLIC_KEY
, &nullItem
) != SECSuccess
) {
525 /* this will generate a key pair, compute the shared secret, */
526 /* derive a key and ukm for the keyEncAlg out of it, encrypt the bulk key with */
527 /* the keyEncAlg, set encKey, keyEncAlg, publicKey etc. */
528 rv
= SecCmsUtilEncryptSymKeyECDH(poolp
, cert
, bulkkey
,
532 &oiok
->id
.originatorPublicKey
.publicKey
);
535 /* other algorithms not supported yet */
536 /* NOTE that we do not support any KEK algorithm */
537 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM
);
546 #define dprintf(args...)
548 #define dprintf(args...) fprintf(stderr, args)
552 SecCmsRecipientInfoUnwrapBulkKey(SecCmsRecipientInfoRef ri
, int subIndex
,
553 SecCertificateRef cert
, SecPrivateKeyRef privkey
, SECOidTag bulkalgtag
)
555 SecSymmetricKeyRef bulkkey
= NULL
;
556 SECAlgorithmID
*encalg
;
558 SecAsn1Item
* enckey
;
561 ri
->cert
= CERT_DupCertificate(cert
);
562 /* mark the recipientInfo so we can find it later */
564 switch (ri
->recipientInfoType
) {
565 case SecCmsRecipientInfoIDKeyTrans
:
566 encalgtag
= SECOID_GetAlgorithmTag(&(ri
->ri
.keyTransRecipientInfo
.keyEncAlg
));
567 enckey
= &(ri
->ri
.keyTransRecipientInfo
.encKey
); /* ignore subIndex */
569 case SEC_OID_PKCS1_RSA_ENCRYPTION
:
570 /* RSA encryption algorithm: */
571 /* get the symmetric (bulk) key by unwrapping it using our private key */
572 bulkkey
= SecCmsUtilDecryptSymKeyRSA(privkey
, enckey
, bulkalgtag
);
575 case SEC_OID_NETSCAPE_SMIME_KEA
:
576 /* FORTEZZA key exchange algorithm */
577 /* the supplemental data is in the parameters of encalg */
578 encalg
= &(ri
->ri
.keyTransRecipientInfo
.keyEncAlg
);
579 bulkkey
= SecCmsUtilDecryptSymKeyMISSI(privkey
, enckey
, encalg
, bulkalgtag
, ri
->cmsg
->pwfn_arg
);
583 error
= SEC_ERROR_UNSUPPORTED_KEYALG
;
587 case SecCmsRecipientInfoIDKeyAgree
:
588 encalgtag
= SECOID_GetAlgorithmTag(&(ri
->ri
.keyAgreeRecipientInfo
.keyEncAlg
));
590 case SEC_OID_X942_DIFFIE_HELMAN_KEY
:
591 /* Diffie-Helman key exchange */
592 /* XXX not yet implemented */
593 /* XXX problem: SEC_OID_X942_DIFFIE_HELMAN_KEY points to a PKCS3 mechanism! */
594 /* we support ephemeral-static DH only, so if the recipientinfo */
595 /* has originator stuff in it, we punt (or do we? shouldn't be that hard...) */
596 /* first, we derive the KEK (a symkey!) using a Derive operation, then we get the */
597 /* content encryption key using a Unwrap op */
598 /* the derive operation has to generate the key using the algorithm in RFC2631 */
599 error
= SEC_ERROR_UNSUPPORTED_KEYALG
;
601 case SEC_OID_DH_SINGLE_STD_SHA1KDF
:
603 /* ephemeral-static ECDH */
604 enckey
= &(ri
->ri
.keyAgreeRecipientInfo
.recipientEncryptedKeys
[subIndex
]->encKey
);
605 encalg
= &(ri
->ri
.keyAgreeRecipientInfo
.keyEncAlg
);
606 SecCmsKeyAgreeRecipientInfo
*kari
= &ri
->ri
.keyAgreeRecipientInfo
;
607 SecCmsOriginatorIdentifierOrKey
*oiok
= &kari
->originatorIdentifierOrKey
;
608 if(oiok
->identifierType
!= SecCmsOriginatorIDOrKeyOriginatorPublicKey
) {
609 dprintf("SEC_OID_EC_PUBLIC_KEY unwrap key: bad oiok.id\n");
610 error
= SEC_ERROR_LIBRARY_FAILURE
;
613 SecCmsOriginatorPublicKey
*opk
= &oiok
->id
.originatorPublicKey
;
614 /* FIXME - verify opk->algorithmIdentifier here? */
615 SecAsn1Item senderPubKey
= opk
->publicKey
;
616 SecAsn1Item
*ukm
= &kari
->ukm
;
617 bulkkey
= SecCmsUtilDecryptSymKeyECDH(privkey
, enckey
, ukm
, encalg
, bulkalgtag
, &senderPubKey
);
621 error
= SEC_ERROR_UNSUPPORTED_KEYALG
;
625 case SecCmsRecipientInfoIDKEK
:
626 /* not supported yet */
627 error
= SEC_ERROR_UNSUPPORTED_KEYALG
;
631 /* XXXX continue here */
635 PORT_SetError(error
);