1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
38 * CMS recipientInfo methods.
40 * $Id: cmsrecinfo.c,v 1.19 2006/07/19 00:36:38 nelson%bolyard.com Exp $
54 nss_cmsrecipientinfo_usessubjectkeyid(NSSCMSRecipientInfo
*ri
)
56 if (ri
->recipientInfoType
== NSSCMSRecipientInfoID_KeyTrans
) {
57 NSSCMSRecipientIdentifier
*rid
;
58 rid
= &ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
;
59 if (rid
->identifierType
== NSSCMSRecipientID_SubjectKeyID
) {
67 * NOTE: fakeContent marks CMSMessage structure which is only used as a carrier
68 * of pwfn_arg and arena pools. In an ideal world, NSSCMSMessage would not have
69 * been exported, and we would have added an ordinary enum to handle this
70 * check. Unfortunatly wo don't have that luxury so we are overloading the
71 * contentTypeTag field. NO code should every try to interpret this content tag
72 * as a real OID tag, or use any fields other than pwfn_arg or poolp of this
73 * CMSMessage for that matter */
74 static const SECOidData fakeContent
;
76 nss_cmsrecipientinfo_create(NSSCMSMessage
*cmsg
,
77 NSSCMSRecipientIDSelector type
,
78 CERTCertificate
*cert
,
79 SECKEYPublicKey
*pubKey
,
84 NSSCMSRecipientInfo
*ri
;
87 SECStatus rv
= SECSuccess
;
88 NSSCMSRecipientEncryptedKey
*rek
;
89 NSSCMSOriginatorIdentifierOrKey
*oiok
;
90 unsigned long version
;
93 CERTSubjectPublicKeyInfo
*spki
, *freeSpki
= NULL
;
94 NSSCMSRecipientIdentifier
*rid
;
95 extern const SEC_ASN1Template NSSCMSRecipientInfoTemplate
[];
98 /* a CMSMessage wasn't supplied, create a fake one to hold the pwfunc
99 * and a private arena pool */
100 cmsg
= NSS_CMSMessage_Create(NULL
);
101 cmsg
->pwfn_arg
= pwfn_arg
;
102 /* mark it as a special cms message */
103 cmsg
->contentInfo
.contentTypeTag
= (SECOidData
*)&fakeContent
;
108 mark
= PORT_ArenaMark(poolp
);
110 ri
= (NSSCMSRecipientInfo
*)PORT_ArenaZAlloc(poolp
, sizeof(NSSCMSRecipientInfo
));
117 /* decode everything from DER */
119 SECStatus rv
= SECITEM_CopyItem(poolp
, &newinput
, DERinput
);
120 if (SECSuccess
!= rv
)
122 rv
= SEC_QuickDERDecodeItem(poolp
, ri
, NSSCMSRecipientInfoTemplate
, &newinput
);
123 if (SECSuccess
!= rv
)
128 case NSSCMSRecipientID_IssuerSN
:
130 ri
->cert
= CERT_DupCertificate(cert
);
131 if (NULL
== ri
->cert
)
133 spki
= &(cert
->subjectPublicKeyInfo
);
137 case NSSCMSRecipientID_SubjectKeyID
:
140 spki
= freeSpki
= SECKEY_CreateSubjectPublicKeyInfo(pubKey
);
144 case NSSCMSRecipientID_BrandNew
:
154 certalgtag
= SECOID_GetAlgorithmTag(&(spki
->algorithm
));
156 rid
= &ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
;
157 switch (certalgtag
) {
158 case SEC_OID_PKCS1_RSA_ENCRYPTION
:
159 ri
->recipientInfoType
= NSSCMSRecipientInfoID_KeyTrans
;
160 rid
->identifierType
= type
;
161 if (type
== NSSCMSRecipientID_IssuerSN
) {
162 rid
->id
.issuerAndSN
= CERT_GetCertIssuerAndSN(poolp
, cert
);
163 if (rid
->id
.issuerAndSN
== NULL
) {
166 } else if (type
== NSSCMSRecipientID_SubjectKeyID
){
167 NSSCMSKeyTransRecipientInfoEx
*riExtra
;
169 rid
->id
.subjectKeyID
= PORT_ArenaNew(poolp
, SECItem
);
170 if (rid
->id
.subjectKeyID
== NULL
) {
172 PORT_SetError(SEC_ERROR_NO_MEMORY
);
175 SECITEM_CopyItem(poolp
, rid
->id
.subjectKeyID
, subjKeyID
);
176 if (rid
->id
.subjectKeyID
->data
== NULL
) {
178 PORT_SetError(SEC_ERROR_NO_MEMORY
);
181 riExtra
= &ri
->ri
.keyTransRecipientInfoEx
;
182 riExtra
->version
= 0;
183 riExtra
->pubKey
= SECKEY_CopyPublicKey(pubKey
);
184 if (riExtra
->pubKey
== NULL
) {
186 PORT_SetError(SEC_ERROR_NO_MEMORY
);
190 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
194 case SEC_OID_X942_DIFFIE_HELMAN_KEY
: /* dh-public-number */
195 PORT_Assert(type
== NSSCMSRecipientID_IssuerSN
);
196 if (type
!= NSSCMSRecipientID_IssuerSN
) {
200 /* a key agreement op */
201 ri
->recipientInfoType
= NSSCMSRecipientInfoID_KeyAgree
;
203 if (ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
.id
.issuerAndSN
== NULL
) {
207 /* we do not support the case where multiple recipients
208 * share the same KeyAgreeRecipientInfo and have multiple RecipientEncryptedKeys
209 * in this case, we would need to walk all the recipientInfos, take the
210 * ones that do KeyAgreement algorithms and join them, algorithm by algorithm
211 * Then, we'd generate ONE ukm and OriginatorIdentifierOrKey */
213 /* only epheremal-static Diffie-Hellman is supported for now
214 * this is the only form of key agreement that provides potential anonymity
215 * of the sender, plus we do not have to include certs in the message */
217 /* force single recipientEncryptedKey for now */
218 if ((rek
= NSS_CMSRecipientEncryptedKey_Create(poolp
)) == NULL
) {
223 /* hardcoded IssuerSN choice for now */
224 rek
->recipientIdentifier
.identifierType
= NSSCMSKeyAgreeRecipientID_IssuerSN
;
225 if ((rek
->recipientIdentifier
.id
.issuerAndSN
= CERT_GetCertIssuerAndSN(poolp
, cert
)) == NULL
) {
230 oiok
= &(ri
->ri
.keyAgreeRecipientInfo
.originatorIdentifierOrKey
);
232 /* see RFC2630 12.3.1.1 */
233 oiok
->identifierType
= NSSCMSOriginatorIDOrKey_OriginatorPublicKey
;
235 rv
= NSS_CMSArray_Add(poolp
, (void ***)&ri
->ri
.keyAgreeRecipientInfo
.recipientEncryptedKeys
,
240 /* other algorithms not supported yet */
241 /* NOTE that we do not support any KEK algorithm */
242 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM
);
247 if (rv
== SECFailure
)
251 switch (ri
->recipientInfoType
) {
252 case NSSCMSRecipientInfoID_KeyTrans
:
253 if (ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
.identifierType
== NSSCMSRecipientID_IssuerSN
)
254 version
= NSS_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_ISSUERSN
;
256 version
= NSS_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_SUBJKEY
;
257 dummy
= SEC_ASN1EncodeInteger(poolp
, &(ri
->ri
.keyTransRecipientInfo
.version
), version
);
261 case NSSCMSRecipientInfoID_KeyAgree
:
262 dummy
= SEC_ASN1EncodeInteger(poolp
, &(ri
->ri
.keyAgreeRecipientInfo
.version
),
263 NSS_CMS_KEYAGREE_RECIPIENT_INFO_VERSION
);
267 case NSSCMSRecipientInfoID_KEK
:
268 /* NOTE: this cannot happen as long as we do not support any KEK algorithm */
269 dummy
= SEC_ASN1EncodeInteger(poolp
, &(ri
->ri
.kekRecipientInfo
.version
),
270 NSS_CMS_KEK_RECIPIENT_INFO_VERSION
);
278 PORT_ArenaUnmark (poolp
, mark
);
280 SECKEY_DestroySubjectPublicKeyInfo(freeSpki
);
284 if (ri
&& ri
->cert
) {
285 CERT_DestroyCertificate(ri
->cert
);
288 SECKEY_DestroySubjectPublicKeyInfo(freeSpki
);
290 PORT_ArenaRelease (poolp
, mark
);
291 if (cmsg
->contentInfo
.contentTypeTag
== &fakeContent
) {
292 NSS_CMSMessage_Destroy(cmsg
);
298 * NSS_CMSRecipientInfo_Create - create a recipientinfo
300 * we currently do not create KeyAgreement recipientinfos with multiple
301 * recipientEncryptedKeys the certificate is supposed to have been
302 * verified by the caller
304 NSSCMSRecipientInfo
*
305 NSS_CMSRecipientInfo_Create(NSSCMSMessage
*cmsg
, CERTCertificate
*cert
)
307 return nss_cmsrecipientinfo_create(cmsg
, NSSCMSRecipientID_IssuerSN
, cert
,
308 NULL
, NULL
, NULL
, NULL
);
311 NSSCMSRecipientInfo
*
312 NSS_CMSRecipientInfo_CreateNew(void* pwfn_arg
)
314 return nss_cmsrecipientinfo_create(NULL
, NSSCMSRecipientID_BrandNew
, NULL
,
315 NULL
, NULL
, pwfn_arg
, NULL
);
318 NSSCMSRecipientInfo
*
319 NSS_CMSRecipientInfo_CreateFromDER(SECItem
* input
, void* pwfn_arg
)
321 return nss_cmsrecipientinfo_create(NULL
, NSSCMSRecipientID_BrandNew
, NULL
,
322 NULL
, NULL
, pwfn_arg
, input
);
326 NSSCMSRecipientInfo
*
327 NSS_CMSRecipientInfo_CreateWithSubjKeyID(NSSCMSMessage
*cmsg
,
329 SECKEYPublicKey
*pubKey
)
331 return nss_cmsrecipientinfo_create(cmsg
, NSSCMSRecipientID_SubjectKeyID
,
332 NULL
, pubKey
, subjKeyID
, NULL
, NULL
);
335 NSSCMSRecipientInfo
*
336 NSS_CMSRecipientInfo_CreateWithSubjKeyIDFromCert(NSSCMSMessage
*cmsg
,
337 CERTCertificate
*cert
)
339 SECKEYPublicKey
*pubKey
= NULL
;
340 SECItem subjKeyID
= {siBuffer
, NULL
, 0};
341 NSSCMSRecipientInfo
*retVal
= NULL
;
343 if (!cmsg
|| !cert
) {
346 pubKey
= CERT_ExtractPublicKey(cert
);
350 if (CERT_FindSubjectKeyIDExtension(cert
, &subjKeyID
) != SECSuccess
||
351 subjKeyID
.data
== NULL
) {
354 retVal
= NSS_CMSRecipientInfo_CreateWithSubjKeyID(cmsg
, &subjKeyID
, pubKey
);
357 SECKEY_DestroyPublicKey(pubKey
);
360 SECITEM_FreeItem(&subjKeyID
, PR_FALSE
);
366 NSS_CMSRecipientInfo_Destroy(NSSCMSRecipientInfo
*ri
)
371 /* version was allocated on the pool, so no need to destroy it */
372 /* issuerAndSN was allocated on the pool, so no need to destroy it */
373 if (ri
->cert
!= NULL
)
374 CERT_DestroyCertificate(ri
->cert
);
376 if (nss_cmsrecipientinfo_usessubjectkeyid(ri
)) {
377 NSSCMSKeyTransRecipientInfoEx
*extra
;
378 extra
= &ri
->ri
.keyTransRecipientInfoEx
;
380 SECKEY_DestroyPublicKey(extra
->pubKey
);
382 if (ri
->cmsg
&& ri
->cmsg
->contentInfo
.contentTypeTag
== &fakeContent
) {
383 NSS_CMSMessage_Destroy(ri
->cmsg
);
390 NSS_CMSRecipientInfo_GetVersion(NSSCMSRecipientInfo
*ri
)
392 unsigned long version
;
393 SECItem
*versionitem
= NULL
;
395 switch (ri
->recipientInfoType
) {
396 case NSSCMSRecipientInfoID_KeyTrans
:
397 /* ignore subIndex */
398 versionitem
= &(ri
->ri
.keyTransRecipientInfo
.version
);
400 case NSSCMSRecipientInfoID_KEK
:
401 /* ignore subIndex */
402 versionitem
= &(ri
->ri
.kekRecipientInfo
.version
);
404 case NSSCMSRecipientInfoID_KeyAgree
:
405 versionitem
= &(ri
->ri
.keyAgreeRecipientInfo
.version
);
409 PORT_Assert(versionitem
);
410 if (versionitem
== NULL
)
413 /* always take apart the SECItem */
414 if (SEC_ASN1DecodeInteger(versionitem
, &version
) != SECSuccess
)
421 NSS_CMSRecipientInfo_GetEncryptedKey(NSSCMSRecipientInfo
*ri
, int subIndex
)
423 SECItem
*enckey
= NULL
;
425 switch (ri
->recipientInfoType
) {
426 case NSSCMSRecipientInfoID_KeyTrans
:
427 /* ignore subIndex */
428 enckey
= &(ri
->ri
.keyTransRecipientInfo
.encKey
);
430 case NSSCMSRecipientInfoID_KEK
:
431 /* ignore subIndex */
432 enckey
= &(ri
->ri
.kekRecipientInfo
.encKey
);
434 case NSSCMSRecipientInfoID_KeyAgree
:
435 enckey
= &(ri
->ri
.keyAgreeRecipientInfo
.recipientEncryptedKeys
[subIndex
]->encKey
);
443 NSS_CMSRecipientInfo_GetKeyEncryptionAlgorithmTag(NSSCMSRecipientInfo
*ri
)
445 SECOidTag encalgtag
= SEC_OID_UNKNOWN
; /* an invalid encryption alg */
447 switch (ri
->recipientInfoType
) {
448 case NSSCMSRecipientInfoID_KeyTrans
:
449 encalgtag
= SECOID_GetAlgorithmTag(&(ri
->ri
.keyTransRecipientInfo
.keyEncAlg
));
451 case NSSCMSRecipientInfoID_KeyAgree
:
452 encalgtag
= SECOID_GetAlgorithmTag(&(ri
->ri
.keyAgreeRecipientInfo
.keyEncAlg
));
454 case NSSCMSRecipientInfoID_KEK
:
455 encalgtag
= SECOID_GetAlgorithmTag(&(ri
->ri
.kekRecipientInfo
.keyEncAlg
));
462 NSS_CMSRecipientInfo_WrapBulkKey(NSSCMSRecipientInfo
*ri
, PK11SymKey
*bulkkey
,
463 SECOidTag bulkalgtag
)
465 CERTCertificate
*cert
;
466 SECOidTag certalgtag
;
467 SECStatus rv
= SECSuccess
;
468 SECItem
*params
= NULL
;
469 NSSCMSRecipientEncryptedKey
*rek
;
470 NSSCMSOriginatorIdentifierOrKey
*oiok
;
471 CERTSubjectPublicKeyInfo
*spki
, *freeSpki
= NULL
;
473 NSSCMSKeyTransRecipientInfoEx
*extra
= NULL
;
474 PRBool usesSubjKeyID
;
476 poolp
= ri
->cmsg
->poolp
;
478 usesSubjKeyID
= nss_cmsrecipientinfo_usessubjectkeyid(ri
);
480 spki
= &cert
->subjectPublicKeyInfo
;
481 certalgtag
= SECOID_GetAlgorithmTag(&(spki
->algorithm
));
482 } else if (usesSubjKeyID
) {
483 extra
= &ri
->ri
.keyTransRecipientInfoEx
;
485 PORT_Assert(extra
->pubKey
);
486 if (!extra
->pubKey
) {
487 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
490 spki
= freeSpki
= SECKEY_CreateSubjectPublicKeyInfo(extra
->pubKey
);
491 certalgtag
= SECOID_GetAlgorithmTag(&spki
->algorithm
);
493 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
497 /* XXX set ri->recipientInfoType to the proper value here */
498 /* or should we look if it's been set already ? */
500 certalgtag
= SECOID_GetAlgorithmTag(&spki
->algorithm
);
501 switch (certalgtag
) {
502 case SEC_OID_PKCS1_RSA_ENCRYPTION
:
503 /* wrap the symkey */
505 rv
= NSS_CMSUtil_EncryptSymKey_RSA(poolp
, cert
, bulkkey
,
506 &ri
->ri
.keyTransRecipientInfo
.encKey
);
507 if (rv
!= SECSuccess
)
509 } else if (usesSubjKeyID
) {
510 PORT_Assert(extra
!= NULL
);
511 rv
= NSS_CMSUtil_EncryptSymKey_RSAPubKey(poolp
, extra
->pubKey
,
512 bulkkey
, &ri
->ri
.keyTransRecipientInfo
.encKey
);
513 if (rv
!= SECSuccess
)
517 rv
= SECOID_SetAlgorithmID(poolp
, &(ri
->ri
.keyTransRecipientInfo
.keyEncAlg
), certalgtag
, NULL
);
519 case SEC_OID_X942_DIFFIE_HELMAN_KEY
: /* dh-public-number */
520 rek
= ri
->ri
.keyAgreeRecipientInfo
.recipientEncryptedKeys
[0];
526 oiok
= &(ri
->ri
.keyAgreeRecipientInfo
.originatorIdentifierOrKey
);
527 PORT_Assert(oiok
->identifierType
== NSSCMSOriginatorIDOrKey_OriginatorPublicKey
);
529 /* see RFC2630 12.3.1.1 */
530 if (SECOID_SetAlgorithmID(poolp
, &oiok
->id
.originatorPublicKey
.algorithmIdentifier
,
531 SEC_OID_X942_DIFFIE_HELMAN_KEY
, NULL
) != SECSuccess
) {
536 /* this will generate a key pair, compute the shared secret, */
537 /* derive a key and ukm for the keyEncAlg out of it, encrypt the bulk key with */
538 /* the keyEncAlg, set encKey, keyEncAlg, publicKey etc. */
539 rv
= NSS_CMSUtil_EncryptSymKey_ESDH(poolp
, cert
, bulkkey
,
541 &ri
->ri
.keyAgreeRecipientInfo
.ukm
,
542 &ri
->ri
.keyAgreeRecipientInfo
.keyEncAlg
,
543 &oiok
->id
.originatorPublicKey
.publicKey
);
547 /* other algorithms not supported yet */
548 /* NOTE that we do not support any KEK algorithm */
549 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM
);
554 SECKEY_DestroySubjectPublicKeyInfo(freeSpki
);
560 NSS_CMSRecipientInfo_UnwrapBulkKey(NSSCMSRecipientInfo
*ri
, int subIndex
,
561 CERTCertificate
*cert
, SECKEYPrivateKey
*privkey
, SECOidTag bulkalgtag
)
563 PK11SymKey
*bulkkey
= NULL
;
564 SECAlgorithmID
*encalg
;
569 ri
->cert
= CERT_DupCertificate(cert
);
570 /* mark the recipientInfo so we can find it later */
572 switch (ri
->recipientInfoType
) {
573 case NSSCMSRecipientInfoID_KeyTrans
:
574 encalg
= &(ri
->ri
.keyTransRecipientInfo
.keyEncAlg
);
575 encalgtag
= SECOID_GetAlgorithmTag(&(ri
->ri
.keyTransRecipientInfo
.keyEncAlg
));
576 enckey
= &(ri
->ri
.keyTransRecipientInfo
.encKey
); /* ignore subIndex */
578 case SEC_OID_PKCS1_RSA_ENCRYPTION
:
579 /* RSA encryption algorithm: */
580 /* get the symmetric (bulk) key by unwrapping it using our private key */
581 bulkkey
= NSS_CMSUtil_DecryptSymKey_RSA(privkey
, enckey
, bulkalgtag
);
583 case SEC_OID_NETSCAPE_SMIME_KEA
:
584 /* FORTEZZA key exchange algorithm */
585 /* the supplemental data is in the parameters of encalg */
586 bulkkey
= NSS_CMSUtil_DecryptSymKey_MISSI(privkey
, enckey
, encalg
, bulkalgtag
, ri
->cmsg
->pwfn_arg
);
589 error
= SEC_ERROR_UNSUPPORTED_KEYALG
;
593 case NSSCMSRecipientInfoID_KeyAgree
:
594 encalg
= &(ri
->ri
.keyAgreeRecipientInfo
.keyEncAlg
);
595 encalgtag
= SECOID_GetAlgorithmTag(&(ri
->ri
.keyAgreeRecipientInfo
.keyEncAlg
));
596 enckey
= &(ri
->ri
.keyAgreeRecipientInfo
.recipientEncryptedKeys
[subIndex
]->encKey
);
598 case SEC_OID_X942_DIFFIE_HELMAN_KEY
:
599 /* Diffie-Helman key exchange */
600 /* XXX not yet implemented */
601 /* XXX problem: SEC_OID_X942_DIFFIE_HELMAN_KEY points to a PKCS3 mechanism! */
602 /* we support ephemeral-static DH only, so if the recipientinfo */
603 /* has originator stuff in it, we punt (or do we? shouldn't be that hard...) */
604 /* first, we derive the KEK (a symkey!) using a Derive operation, then we get the */
605 /* content encryption key using a Unwrap op */
606 /* the derive operation has to generate the key using the algorithm in RFC2631 */
607 error
= SEC_ERROR_UNSUPPORTED_KEYALG
;
610 error
= SEC_ERROR_UNSUPPORTED_KEYALG
;
614 case NSSCMSRecipientInfoID_KEK
:
615 encalg
= &(ri
->ri
.kekRecipientInfo
.keyEncAlg
);
616 encalgtag
= SECOID_GetAlgorithmTag(&(ri
->ri
.kekRecipientInfo
.keyEncAlg
));
617 enckey
= &(ri
->ri
.kekRecipientInfo
.encKey
);
618 /* not supported yet */
619 error
= SEC_ERROR_UNSUPPORTED_KEYALG
;
623 /* XXXX continue here */
630 SECStatus
NSS_CMSRecipientInfo_GetCertAndKey(NSSCMSRecipientInfo
*ri
,
631 CERTCertificate
** retcert
,
632 SECKEYPrivateKey
** retkey
)
634 CERTCertificate
* cert
= NULL
;
635 NSSCMSRecipient
** recipients
= NULL
;
636 NSSCMSRecipientInfo
* recipientInfos
[2];
637 SECStatus rv
= SECSuccess
;
638 SECKEYPrivateKey
* key
= NULL
;
643 if (!retcert
&& !retkey
) {
644 /* nothing requested, nothing found, success */
656 cert
= CERT_DupCertificate(ri
->cert
);
661 if (SECSuccess
== rv
&& !cert
) {
662 /* we don't have the cert, we have to look for it */
663 /* first build an NSS_CMSRecipient */
664 recipientInfos
[0] = ri
;
665 recipientInfos
[1] = NULL
;
667 recipients
= nss_cms_recipient_list_create(recipientInfos
);
669 /* now look for the cert and key */
670 if (0 == PK11_FindCertAndKeyByRecipientListNew(recipients
,
671 ri
->cmsg
->pwfn_arg
)) {
672 cert
= CERT_DupCertificate(recipients
[0]->cert
);
673 key
= SECKEY_CopyPrivateKey(recipients
[0]->privkey
);
678 nss_cms_recipient_list_destroy(recipients
);
683 } else if (SECSuccess
== rv
&& cert
&& retkey
) {
684 /* we have the cert, we just need the key now */
685 key
= PK11_FindPrivateKeyFromCert(cert
->slot
, cert
, ri
->cmsg
->pwfn_arg
);
691 CERT_DestroyCertificate(cert
);
698 SECKEY_DestroyPrivateKey(key
);
705 SECStatus
NSS_CMSRecipientInfo_Encode(PRArenaPool
* poolp
,
706 const NSSCMSRecipientInfo
*src
,
709 extern const SEC_ASN1Template NSSCMSRecipientInfoTemplate
[];
710 SECStatus rv
= SECFailure
;
711 if (!src
|| !returned
) {
712 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
713 } else if (SEC_ASN1EncodeItem(poolp
, returned
, src
,
714 NSSCMSRecipientInfoTemplate
)) {