1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/smime/cmssigdata.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1141 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/* 1.9 + * CMS signedData methods. 1.10 + */ 1.11 + 1.12 +#include "cmslocal.h" 1.13 + 1.14 +#include "cert.h" 1.15 +/*#include "cdbhdl.h"*/ 1.16 +#include "secasn1.h" 1.17 +#include "secitem.h" 1.18 +#include "secoid.h" 1.19 +#include "pk11func.h" 1.20 +#include "secerr.h" 1.21 + 1.22 +NSSCMSSignedData * 1.23 +NSS_CMSSignedData_Create(NSSCMSMessage *cmsg) 1.24 +{ 1.25 + void *mark; 1.26 + NSSCMSSignedData *sigd; 1.27 + PLArenaPool *poolp; 1.28 + 1.29 + if (!cmsg) { 1.30 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.31 + return NULL; 1.32 + } 1.33 + 1.34 + poolp = cmsg->poolp; 1.35 + 1.36 + mark = PORT_ArenaMark(poolp); 1.37 + 1.38 + sigd = (NSSCMSSignedData *)PORT_ArenaZAlloc (poolp, sizeof(NSSCMSSignedData)); 1.39 + if (sigd == NULL) 1.40 + goto loser; 1.41 + 1.42 + sigd->cmsg = cmsg; 1.43 + 1.44 + /* signerInfos, certs, certlists, crls are all empty */ 1.45 + /* version is set in NSS_CMSSignedData_Finalize() */ 1.46 + 1.47 + PORT_ArenaUnmark(poolp, mark); 1.48 + return sigd; 1.49 + 1.50 +loser: 1.51 + PORT_ArenaRelease(poolp, mark); 1.52 + return NULL; 1.53 +} 1.54 + 1.55 +void 1.56 +NSS_CMSSignedData_Destroy(NSSCMSSignedData *sigd) 1.57 +{ 1.58 + CERTCertificate **certs, **tempCerts, *cert; 1.59 + CERTCertificateList **certlists, *certlist; 1.60 + NSSCMSSignerInfo **signerinfos, *si; 1.61 + 1.62 + if (sigd == NULL) 1.63 + return; 1.64 + 1.65 + certs = sigd->certs; 1.66 + tempCerts = sigd->tempCerts; 1.67 + certlists = sigd->certLists; 1.68 + signerinfos = sigd->signerInfos; 1.69 + 1.70 + if (certs != NULL) { 1.71 + while ((cert = *certs++) != NULL) 1.72 + CERT_DestroyCertificate (cert); 1.73 + } 1.74 + 1.75 + if (tempCerts != NULL) { 1.76 + while ((cert = *tempCerts++) != NULL) 1.77 + CERT_DestroyCertificate (cert); 1.78 + } 1.79 + 1.80 + if (certlists != NULL) { 1.81 + while ((certlist = *certlists++) != NULL) 1.82 + CERT_DestroyCertificateList (certlist); 1.83 + } 1.84 + 1.85 + if (signerinfos != NULL) { 1.86 + while ((si = *signerinfos++) != NULL) 1.87 + NSS_CMSSignerInfo_Destroy(si); 1.88 + } 1.89 + 1.90 + /* everything's in a pool, so don't worry about the storage */ 1.91 + NSS_CMSContentInfo_Destroy(&(sigd->contentInfo)); 1.92 + 1.93 +} 1.94 + 1.95 +/* 1.96 + * NSS_CMSSignedData_Encode_BeforeStart - do all the necessary things to a SignedData 1.97 + * before start of encoding. 1.98 + * 1.99 + * In detail: 1.100 + * - find out about the right value to put into sigd->version 1.101 + * - come up with a list of digestAlgorithms (which should be the union of the algorithms 1.102 + * in the signerinfos). 1.103 + * If we happen to have a pre-set list of algorithms (and digest values!), we 1.104 + * check if we have all the signerinfos' algorithms. If not, this is an error. 1.105 + */ 1.106 +SECStatus 1.107 +NSS_CMSSignedData_Encode_BeforeStart(NSSCMSSignedData *sigd) 1.108 +{ 1.109 + NSSCMSSignerInfo *signerinfo; 1.110 + SECOidTag digestalgtag; 1.111 + SECItem *dummy; 1.112 + int version; 1.113 + SECStatus rv; 1.114 + PRBool haveDigests = PR_FALSE; 1.115 + int n, i; 1.116 + PLArenaPool *poolp; 1.117 + 1.118 + if (!sigd) { 1.119 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.120 + return SECFailure; 1.121 + } 1.122 + 1.123 + poolp = sigd->cmsg->poolp; 1.124 + 1.125 + /* we assume that we have precomputed digests if there is a list of algorithms, and */ 1.126 + /* a chunk of data for each of those algorithms */ 1.127 + if (sigd->digestAlgorithms != NULL && sigd->digests != NULL) { 1.128 + for (i=0; sigd->digestAlgorithms[i] != NULL; i++) { 1.129 + if (sigd->digests[i] == NULL) 1.130 + break; 1.131 + } 1.132 + if (sigd->digestAlgorithms[i] == NULL) /* reached the end of the array? */ 1.133 + haveDigests = PR_TRUE; /* yes: we must have all the digests */ 1.134 + } 1.135 + 1.136 + version = NSS_CMS_SIGNED_DATA_VERSION_BASIC; 1.137 + 1.138 + /* RFC2630 5.1 "version is the syntax version number..." */ 1.139 + if (NSS_CMSContentInfo_GetContentTypeTag(&(sigd->contentInfo)) != SEC_OID_PKCS7_DATA) 1.140 + version = NSS_CMS_SIGNED_DATA_VERSION_EXT; 1.141 + 1.142 + /* prepare all the SignerInfos (there may be none) */ 1.143 + for (i=0; i < NSS_CMSSignedData_SignerInfoCount(sigd); i++) { 1.144 + signerinfo = NSS_CMSSignedData_GetSignerInfo(sigd, i); 1.145 + 1.146 + /* RFC2630 5.1 "version is the syntax version number..." */ 1.147 + if (NSS_CMSSignerInfo_GetVersion(signerinfo) != NSS_CMS_SIGNER_INFO_VERSION_ISSUERSN) 1.148 + version = NSS_CMS_SIGNED_DATA_VERSION_EXT; 1.149 + 1.150 + /* collect digestAlgorithms from SignerInfos */ 1.151 + /* (we need to know which algorithms we have when the content comes in) */ 1.152 + /* do not overwrite any existing digestAlgorithms (and digest) */ 1.153 + digestalgtag = NSS_CMSSignerInfo_GetDigestAlgTag(signerinfo); 1.154 + n = NSS_CMSAlgArray_GetIndexByAlgTag(sigd->digestAlgorithms, digestalgtag); 1.155 + if (n < 0 && haveDigests) { 1.156 + /* oops, there is a digestalg we do not have a digest for */ 1.157 + /* but we were supposed to have all the digests already... */ 1.158 + goto loser; 1.159 + } else if (n < 0) { 1.160 + /* add the digestAlgorithm & a NULL digest */ 1.161 + rv = NSS_CMSSignedData_AddDigest(poolp, sigd, digestalgtag, NULL); 1.162 + if (rv != SECSuccess) 1.163 + goto loser; 1.164 + } else { 1.165 + /* found it, nothing to do */ 1.166 + } 1.167 + } 1.168 + 1.169 + dummy = SEC_ASN1EncodeInteger(poolp, &(sigd->version), (long)version); 1.170 + if (dummy == NULL) 1.171 + return SECFailure; 1.172 + 1.173 + /* this is a SET OF, so we need to sort them guys */ 1.174 + rv = NSS_CMSArray_SortByDER((void **)sigd->digestAlgorithms, 1.175 + SEC_ASN1_GET(SECOID_AlgorithmIDTemplate), 1.176 + (void **)sigd->digests); 1.177 + if (rv != SECSuccess) 1.178 + return SECFailure; 1.179 + 1.180 + return SECSuccess; 1.181 + 1.182 +loser: 1.183 + return SECFailure; 1.184 +} 1.185 + 1.186 +SECStatus 1.187 +NSS_CMSSignedData_Encode_BeforeData(NSSCMSSignedData *sigd) 1.188 +{ 1.189 + SECStatus rv; 1.190 + if (!sigd) { 1.191 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.192 + return SECFailure; 1.193 + } 1.194 + rv = NSS_CMSContentInfo_Private_Init(&sigd->contentInfo); 1.195 + if (rv != SECSuccess) { 1.196 + return SECFailure; 1.197 + } 1.198 + /* set up the digests */ 1.199 + if (sigd->digests && sigd->digests[0]) { 1.200 + sigd->contentInfo.privateInfo->digcx = NULL; /* don't attempt to make new ones. */ 1.201 + } else if (sigd->digestAlgorithms != NULL) { 1.202 + sigd->contentInfo.privateInfo->digcx = 1.203 + NSS_CMSDigestContext_StartMultiple(sigd->digestAlgorithms); 1.204 + if (sigd->contentInfo.privateInfo->digcx == NULL) 1.205 + return SECFailure; 1.206 + } 1.207 + return SECSuccess; 1.208 +} 1.209 + 1.210 +/* 1.211 + * NSS_CMSSignedData_Encode_AfterData - do all the necessary things to a SignedData 1.212 + * after all the encapsulated data was passed through the encoder. 1.213 + * 1.214 + * In detail: 1.215 + * - create the signatures in all the SignerInfos 1.216 + * 1.217 + * Please note that nothing is done to the Certificates and CRLs in the message - this 1.218 + * is entirely the responsibility of our callers. 1.219 + */ 1.220 +SECStatus 1.221 +NSS_CMSSignedData_Encode_AfterData(NSSCMSSignedData *sigd) 1.222 +{ 1.223 + NSSCMSSignerInfo **signerinfos, *signerinfo; 1.224 + NSSCMSContentInfo *cinfo; 1.225 + SECOidTag digestalgtag; 1.226 + SECStatus ret = SECFailure; 1.227 + SECStatus rv; 1.228 + SECItem *contentType; 1.229 + int certcount; 1.230 + int i, ci, cli, n, rci, si; 1.231 + PLArenaPool *poolp; 1.232 + CERTCertificateList *certlist; 1.233 + extern const SEC_ASN1Template NSSCMSSignerInfoTemplate[]; 1.234 + 1.235 + if (!sigd) { 1.236 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.237 + return SECFailure; 1.238 + } 1.239 + 1.240 + poolp = sigd->cmsg->poolp; 1.241 + cinfo = &(sigd->contentInfo); 1.242 + 1.243 + /* did we have digest calculation going on? */ 1.244 + if (cinfo->privateInfo && cinfo->privateInfo->digcx) { 1.245 + rv = NSS_CMSDigestContext_FinishMultiple(cinfo->privateInfo->digcx, poolp, 1.246 + &(sigd->digests)); 1.247 + /* error has been set by NSS_CMSDigestContext_FinishMultiple */ 1.248 + cinfo->privateInfo->digcx = NULL; 1.249 + if (rv != SECSuccess) 1.250 + goto loser; 1.251 + } 1.252 + 1.253 + signerinfos = sigd->signerInfos; 1.254 + certcount = 0; 1.255 + 1.256 + /* prepare all the SignerInfos (there may be none) */ 1.257 + for (i=0; i < NSS_CMSSignedData_SignerInfoCount(sigd); i++) { 1.258 + signerinfo = NSS_CMSSignedData_GetSignerInfo(sigd, i); 1.259 + 1.260 + /* find correct digest for this signerinfo */ 1.261 + digestalgtag = NSS_CMSSignerInfo_GetDigestAlgTag(signerinfo); 1.262 + n = NSS_CMSAlgArray_GetIndexByAlgTag(sigd->digestAlgorithms, digestalgtag); 1.263 + if (n < 0 || sigd->digests == NULL || sigd->digests[n] == NULL) { 1.264 + /* oops - digest not found */ 1.265 + PORT_SetError(SEC_ERROR_DIGEST_NOT_FOUND); 1.266 + goto loser; 1.267 + } 1.268 + 1.269 + /* XXX if our content is anything else but data, we need to force the 1.270 + * presence of signed attributes (RFC2630 5.3 "signedAttributes is a 1.271 + * collection...") */ 1.272 + 1.273 + /* pass contentType here as we want a contentType attribute */ 1.274 + if ((contentType = NSS_CMSContentInfo_GetContentTypeOID(cinfo)) == NULL) 1.275 + goto loser; 1.276 + 1.277 + /* sign the thing */ 1.278 + rv = NSS_CMSSignerInfo_Sign(signerinfo, sigd->digests[n], contentType); 1.279 + if (rv != SECSuccess) 1.280 + goto loser; 1.281 + 1.282 + /* while we're at it, count number of certs in certLists */ 1.283 + certlist = NSS_CMSSignerInfo_GetCertList(signerinfo); 1.284 + if (certlist) 1.285 + certcount += certlist->len; 1.286 + } 1.287 + 1.288 + /* this is a SET OF, so we need to sort them guys */ 1.289 + rv = NSS_CMSArray_SortByDER((void **)signerinfos, NSSCMSSignerInfoTemplate, NULL); 1.290 + if (rv != SECSuccess) 1.291 + goto loser; 1.292 + 1.293 + /* 1.294 + * now prepare certs & crls 1.295 + */ 1.296 + 1.297 + /* count the rest of the certs */ 1.298 + if (sigd->certs != NULL) { 1.299 + for (ci = 0; sigd->certs[ci] != NULL; ci++) 1.300 + certcount++; 1.301 + } 1.302 + 1.303 + if (sigd->certLists != NULL) { 1.304 + for (cli = 0; sigd->certLists[cli] != NULL; cli++) 1.305 + certcount += sigd->certLists[cli]->len; 1.306 + } 1.307 + 1.308 + if (certcount == 0) { 1.309 + sigd->rawCerts = NULL; 1.310 + } else { 1.311 + /* 1.312 + * Combine all of the certs and cert chains into rawcerts. 1.313 + * Note: certcount is an upper bound; we may not need that many slots 1.314 + * but we will allocate anyway to avoid having to do another pass. 1.315 + * (The temporary space saving is not worth it.) 1.316 + * 1.317 + * XXX ARGH - this NEEDS to be fixed. need to come up with a decent 1.318 + * SetOfDERcertficates implementation 1.319 + */ 1.320 + sigd->rawCerts = (SECItem **)PORT_ArenaAlloc(poolp, (certcount + 1) * sizeof(SECItem *)); 1.321 + if (sigd->rawCerts == NULL) 1.322 + return SECFailure; 1.323 + 1.324 + /* 1.325 + * XXX Want to check for duplicates and not add *any* cert that is 1.326 + * already in the set. This will be more important when we start 1.327 + * dealing with larger sets of certs, dual-key certs (signing and 1.328 + * encryption), etc. For the time being we can slide by... 1.329 + * 1.330 + * XXX ARGH - this NEEDS to be fixed. need to come up with a decent 1.331 + * SetOfDERcertficates implementation 1.332 + */ 1.333 + rci = 0; 1.334 + if (signerinfos != NULL) { 1.335 + for (si = 0; signerinfos[si] != NULL; si++) { 1.336 + signerinfo = signerinfos[si]; 1.337 + for (ci = 0; ci < signerinfo->certList->len; ci++) 1.338 + sigd->rawCerts[rci++] = &(signerinfo->certList->certs[ci]); 1.339 + } 1.340 + } 1.341 + 1.342 + if (sigd->certs != NULL) { 1.343 + for (ci = 0; sigd->certs[ci] != NULL; ci++) 1.344 + sigd->rawCerts[rci++] = &(sigd->certs[ci]->derCert); 1.345 + } 1.346 + 1.347 + if (sigd->certLists != NULL) { 1.348 + for (cli = 0; sigd->certLists[cli] != NULL; cli++) { 1.349 + for (ci = 0; ci < sigd->certLists[cli]->len; ci++) 1.350 + sigd->rawCerts[rci++] = &(sigd->certLists[cli]->certs[ci]); 1.351 + } 1.352 + } 1.353 + 1.354 + sigd->rawCerts[rci] = NULL; 1.355 + 1.356 + /* this is a SET OF, so we need to sort them guys - we have the DER already, though */ 1.357 + NSS_CMSArray_Sort((void **)sigd->rawCerts, NSS_CMSUtil_DERCompare, NULL, NULL); 1.358 + } 1.359 + 1.360 + ret = SECSuccess; 1.361 + 1.362 +loser: 1.363 + return ret; 1.364 +} 1.365 + 1.366 +SECStatus 1.367 +NSS_CMSSignedData_Decode_BeforeData(NSSCMSSignedData *sigd) 1.368 +{ 1.369 + SECStatus rv; 1.370 + if (!sigd) { 1.371 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.372 + return SECFailure; 1.373 + } 1.374 + rv = NSS_CMSContentInfo_Private_Init(&sigd->contentInfo); 1.375 + if (rv != SECSuccess) { 1.376 + return SECFailure; 1.377 + } 1.378 + /* handle issue with Windows 2003 servers and kerberos */ 1.379 + if (sigd->digestAlgorithms != NULL) { 1.380 + int i; 1.381 + for (i=0; sigd->digestAlgorithms[i] != NULL; i++) { 1.382 + SECAlgorithmID *algid = sigd->digestAlgorithms[i]; 1.383 + SECOidTag senttag= SECOID_FindOIDTag(&algid->algorithm); 1.384 + SECOidTag maptag = NSS_CMSUtil_MapSignAlgs(senttag); 1.385 + 1.386 + if (maptag != senttag) { 1.387 + SECOidData *hashoid = SECOID_FindOIDByTag(maptag); 1.388 + rv = SECITEM_CopyItem(sigd->cmsg->poolp, &algid->algorithm 1.389 + ,&hashoid->oid); 1.390 + if (rv != SECSuccess) { 1.391 + return rv; 1.392 + } 1.393 + } 1.394 + } 1.395 + } 1.396 + 1.397 + /* set up the digests */ 1.398 + if (sigd->digestAlgorithms != NULL && sigd->digests == NULL) { 1.399 + /* if digests are already there, do nothing */ 1.400 + sigd->contentInfo.privateInfo->digcx = NSS_CMSDigestContext_StartMultiple(sigd->digestAlgorithms); 1.401 + if (sigd->contentInfo.privateInfo->digcx == NULL) 1.402 + return SECFailure; 1.403 + } 1.404 + return SECSuccess; 1.405 +} 1.406 + 1.407 +/* 1.408 + * NSS_CMSSignedData_Decode_AfterData - do all the necessary things to a 1.409 + * SignedData after all the encapsulated data was passed through the decoder. 1.410 + */ 1.411 +SECStatus 1.412 +NSS_CMSSignedData_Decode_AfterData(NSSCMSSignedData *sigd) 1.413 +{ 1.414 + SECStatus rv = SECSuccess; 1.415 + 1.416 + if (!sigd) { 1.417 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.418 + return SECFailure; 1.419 + } 1.420 + 1.421 + /* did we have digest calculation going on? */ 1.422 + if (sigd->contentInfo.privateInfo && sigd->contentInfo.privateInfo->digcx) { 1.423 + rv = NSS_CMSDigestContext_FinishMultiple(sigd->contentInfo.privateInfo->digcx, 1.424 + sigd->cmsg->poolp, &(sigd->digests)); 1.425 + /* error set by NSS_CMSDigestContext_FinishMultiple */ 1.426 + sigd->contentInfo.privateInfo->digcx = NULL; 1.427 + } 1.428 + return rv; 1.429 +} 1.430 + 1.431 +/* 1.432 + * NSS_CMSSignedData_Decode_AfterEnd - do all the necessary things to a SignedData 1.433 + * after all decoding is finished. 1.434 + */ 1.435 +SECStatus 1.436 +NSS_CMSSignedData_Decode_AfterEnd(NSSCMSSignedData *sigd) 1.437 +{ 1.438 + NSSCMSSignerInfo **signerinfos = NULL; 1.439 + int i; 1.440 + 1.441 + if (!sigd) { 1.442 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.443 + return SECFailure; 1.444 + } 1.445 + 1.446 + /* set cmsg for all the signerinfos */ 1.447 + signerinfos = sigd->signerInfos; 1.448 + 1.449 + /* set cmsg for all the signerinfos */ 1.450 + if (signerinfos) { 1.451 + for (i = 0; signerinfos[i] != NULL; i++) 1.452 + signerinfos[i]->cmsg = sigd->cmsg; 1.453 + } 1.454 + 1.455 + return SECSuccess; 1.456 +} 1.457 + 1.458 +/* 1.459 + * NSS_CMSSignedData_GetSignerInfos - retrieve the SignedData's signer list 1.460 + */ 1.461 +NSSCMSSignerInfo ** 1.462 +NSS_CMSSignedData_GetSignerInfos(NSSCMSSignedData *sigd) 1.463 +{ 1.464 + if (!sigd) { 1.465 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.466 + return NULL; 1.467 + } 1.468 + return sigd->signerInfos; 1.469 +} 1.470 + 1.471 +int 1.472 +NSS_CMSSignedData_SignerInfoCount(NSSCMSSignedData *sigd) 1.473 +{ 1.474 + if (!sigd) { 1.475 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.476 + return 0; 1.477 + } 1.478 + return NSS_CMSArray_Count((void **)sigd->signerInfos); 1.479 +} 1.480 + 1.481 +NSSCMSSignerInfo * 1.482 +NSS_CMSSignedData_GetSignerInfo(NSSCMSSignedData *sigd, int i) 1.483 +{ 1.484 + if (!sigd) { 1.485 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.486 + return NULL; 1.487 + } 1.488 + return sigd->signerInfos[i]; 1.489 +} 1.490 + 1.491 +/* 1.492 + * NSS_CMSSignedData_GetDigestAlgs - retrieve the SignedData's digest algorithm list 1.493 + */ 1.494 +SECAlgorithmID ** 1.495 +NSS_CMSSignedData_GetDigestAlgs(NSSCMSSignedData *sigd) 1.496 +{ 1.497 + if (!sigd) { 1.498 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.499 + return NULL; 1.500 + } 1.501 + return sigd->digestAlgorithms; 1.502 +} 1.503 + 1.504 +/* 1.505 + * NSS_CMSSignedData_GetContentInfo - return pointer to this signedData's contentinfo 1.506 + */ 1.507 +NSSCMSContentInfo * 1.508 +NSS_CMSSignedData_GetContentInfo(NSSCMSSignedData *sigd) 1.509 +{ 1.510 + if (!sigd) { 1.511 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.512 + return NULL; 1.513 + } 1.514 + return &(sigd->contentInfo); 1.515 +} 1.516 + 1.517 +/* 1.518 + * NSS_CMSSignedData_GetCertificateList - retrieve the SignedData's certificate list 1.519 + */ 1.520 +SECItem ** 1.521 +NSS_CMSSignedData_GetCertificateList(NSSCMSSignedData *sigd) 1.522 +{ 1.523 + if (!sigd) { 1.524 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.525 + return NULL; 1.526 + } 1.527 + return sigd->rawCerts; 1.528 +} 1.529 + 1.530 +SECStatus 1.531 +NSS_CMSSignedData_ImportCerts(NSSCMSSignedData *sigd, CERTCertDBHandle *certdb, 1.532 + SECCertUsage certusage, PRBool keepcerts) 1.533 +{ 1.534 + int certcount; 1.535 + CERTCertificate **certArray = NULL; 1.536 + CERTCertList *certList = NULL; 1.537 + CERTCertListNode *node; 1.538 + SECStatus rv; 1.539 + SECItem **rawArray; 1.540 + int i; 1.541 + PRTime now; 1.542 + 1.543 + if (!sigd) { 1.544 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.545 + return SECFailure; 1.546 + } 1.547 + 1.548 + certcount = NSS_CMSArray_Count((void **)sigd->rawCerts); 1.549 + 1.550 + /* get the certs in the temp DB */ 1.551 + rv = CERT_ImportCerts(certdb, certusage, certcount, sigd->rawCerts, 1.552 + &certArray, PR_FALSE, PR_FALSE, NULL); 1.553 + if (rv != SECSuccess) { 1.554 + goto loser; 1.555 + } 1.556 + 1.557 + /* save the certs so they don't get destroyed */ 1.558 + for (i=0; i < certcount; i++) { 1.559 + CERTCertificate *cert = certArray[i]; 1.560 + if (cert) 1.561 + NSS_CMSSignedData_AddTempCertificate(sigd, cert); 1.562 + } 1.563 + 1.564 + if (!keepcerts) { 1.565 + goto done; 1.566 + } 1.567 + 1.568 + /* build a CertList for filtering */ 1.569 + certList = CERT_NewCertList(); 1.570 + if (certList == NULL) { 1.571 + rv = SECFailure; 1.572 + goto loser; 1.573 + } 1.574 + for (i=0; i < certcount; i++) { 1.575 + CERTCertificate *cert = certArray[i]; 1.576 + if (cert) 1.577 + cert = CERT_DupCertificate(cert); 1.578 + if (cert) 1.579 + CERT_AddCertToListTail(certList,cert); 1.580 + } 1.581 + 1.582 + /* filter out the certs we don't want */ 1.583 + rv = CERT_FilterCertListByUsage(certList,certusage, PR_FALSE); 1.584 + if (rv != SECSuccess) { 1.585 + goto loser; 1.586 + } 1.587 + 1.588 + /* go down the remaining list of certs and verify that they have 1.589 + * valid chains, then import them. 1.590 + */ 1.591 + now = PR_Now(); 1.592 + for (node = CERT_LIST_HEAD(certList) ; !CERT_LIST_END(node,certList); 1.593 + node= CERT_LIST_NEXT(node)) { 1.594 + CERTCertificateList *certChain; 1.595 + 1.596 + if (CERT_VerifyCert(certdb, node->cert, 1.597 + PR_TRUE, certusage, now, NULL, NULL) != SECSuccess) { 1.598 + continue; 1.599 + } 1.600 + 1.601 + certChain = CERT_CertChainFromCert(node->cert, certusage, PR_FALSE); 1.602 + if (!certChain) { 1.603 + continue; 1.604 + } 1.605 + 1.606 + /* 1.607 + * CertChain returns an array of SECItems, import expects an array of 1.608 + * SECItem pointers. Create the SECItem Pointers from the array of 1.609 + * SECItems. 1.610 + */ 1.611 + rawArray = (SECItem **)PORT_Alloc(certChain->len*sizeof (SECItem *)); 1.612 + if (!rawArray) { 1.613 + CERT_DestroyCertificateList(certChain); 1.614 + continue; 1.615 + } 1.616 + for (i=0; i < certChain->len; i++) { 1.617 + rawArray[i] = &certChain->certs[i]; 1.618 + } 1.619 + (void )CERT_ImportCerts(certdb, certusage, certChain->len, 1.620 + rawArray, NULL, keepcerts, PR_FALSE, NULL); 1.621 + PORT_Free(rawArray); 1.622 + CERT_DestroyCertificateList(certChain); 1.623 + } 1.624 + 1.625 + rv = SECSuccess; 1.626 + 1.627 + /* XXX CRL handling */ 1.628 + 1.629 +done: 1.630 + if (sigd->signerInfos != NULL) { 1.631 + /* fill in all signerinfo's certs */ 1.632 + for (i = 0; sigd->signerInfos[i] != NULL; i++) 1.633 + (void)NSS_CMSSignerInfo_GetSigningCertificate( 1.634 + sigd->signerInfos[i], certdb); 1.635 + } 1.636 + 1.637 +loser: 1.638 + /* now free everything */ 1.639 + if (certArray) { 1.640 + CERT_DestroyCertArray(certArray,certcount); 1.641 + } 1.642 + if (certList) { 1.643 + CERT_DestroyCertList(certList); 1.644 + } 1.645 + 1.646 + return rv; 1.647 +} 1.648 + 1.649 +/* 1.650 + * XXX the digests need to be passed in BETWEEN the decoding and the verification in case 1.651 + * of external signatures! 1.652 + */ 1.653 + 1.654 +/* 1.655 + * NSS_CMSSignedData_VerifySignerInfo - check the signatures. 1.656 + * 1.657 + * The digests were either calculated during decoding (and are stored in the 1.658 + * signedData itself) or set after decoding using NSS_CMSSignedData_SetDigests. 1.659 + * 1.660 + * The verification checks if the signing cert is valid and has a trusted chain 1.661 + * for the purpose specified by "certusage". 1.662 + */ 1.663 +SECStatus 1.664 +NSS_CMSSignedData_VerifySignerInfo(NSSCMSSignedData *sigd, int i, 1.665 + CERTCertDBHandle *certdb, SECCertUsage certusage) 1.666 +{ 1.667 + NSSCMSSignerInfo *signerinfo; 1.668 + NSSCMSContentInfo *cinfo; 1.669 + SECOidData *algiddata; 1.670 + SECItem *contentType, *digest; 1.671 + SECOidTag oidTag; 1.672 + SECStatus rv; 1.673 + 1.674 + if (!sigd) { 1.675 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.676 + return SECFailure; 1.677 + } 1.678 + 1.679 + cinfo = &(sigd->contentInfo); 1.680 + 1.681 + signerinfo = sigd->signerInfos[i]; 1.682 + 1.683 + /* verify certificate */ 1.684 + rv = NSS_CMSSignerInfo_VerifyCertificate(signerinfo, certdb, certusage); 1.685 + if (rv != SECSuccess) 1.686 + return rv; /* error is set */ 1.687 + 1.688 + /* find digest and contentType for signerinfo */ 1.689 + algiddata = NSS_CMSSignerInfo_GetDigestAlg(signerinfo); 1.690 + oidTag = algiddata ? algiddata->offset : SEC_OID_UNKNOWN; 1.691 + digest = NSS_CMSSignedData_GetDigestValue(sigd, oidTag); 1.692 + /* NULL digest is acceptable. */ 1.693 + contentType = NSS_CMSContentInfo_GetContentTypeOID(cinfo); 1.694 + /* NULL contentType is acceptable. */ 1.695 + 1.696 + /* now verify signature */ 1.697 + rv = NSS_CMSSignerInfo_Verify(signerinfo, digest, contentType); 1.698 + return rv; 1.699 +} 1.700 + 1.701 +/* 1.702 + * NSS_CMSSignedData_VerifyCertsOnly - verify the certs in a certs-only message 1.703 + */ 1.704 +SECStatus 1.705 +NSS_CMSSignedData_VerifyCertsOnly(NSSCMSSignedData *sigd, 1.706 + CERTCertDBHandle *certdb, 1.707 + SECCertUsage usage) 1.708 +{ 1.709 + CERTCertificate *cert; 1.710 + SECStatus rv = SECSuccess; 1.711 + int i; 1.712 + int count; 1.713 + PRTime now; 1.714 + 1.715 + if (!sigd || !certdb || !sigd->rawCerts) { 1.716 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.717 + return SECFailure; 1.718 + } 1.719 + 1.720 + count = NSS_CMSArray_Count((void**)sigd->rawCerts); 1.721 + now = PR_Now(); 1.722 + for (i=0; i < count; i++) { 1.723 + if (sigd->certs && sigd->certs[i]) { 1.724 + cert = CERT_DupCertificate(sigd->certs[i]); 1.725 + } else { 1.726 + cert = CERT_FindCertByDERCert(certdb, sigd->rawCerts[i]); 1.727 + if (!cert) { 1.728 + rv = SECFailure; 1.729 + break; 1.730 + } 1.731 + } 1.732 + rv |= CERT_VerifyCert(certdb, cert, PR_TRUE, usage, now, 1.733 + NULL, NULL); 1.734 + CERT_DestroyCertificate(cert); 1.735 + } 1.736 + 1.737 + return rv; 1.738 +} 1.739 + 1.740 +/* 1.741 + * NSS_CMSSignedData_HasDigests - see if we have digests in place 1.742 + */ 1.743 +PRBool 1.744 +NSS_CMSSignedData_HasDigests(NSSCMSSignedData *sigd) 1.745 +{ 1.746 + if (!sigd) { 1.747 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.748 + return PR_FALSE; 1.749 + } 1.750 + return (sigd->digests != NULL); 1.751 +} 1.752 + 1.753 +SECStatus 1.754 +NSS_CMSSignedData_AddCertList(NSSCMSSignedData *sigd, CERTCertificateList *certlist) 1.755 +{ 1.756 + SECStatus rv; 1.757 + 1.758 + if (!sigd || !certlist) { 1.759 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.760 + return SECFailure; 1.761 + } 1.762 + 1.763 + /* XXX memory?? a certlist has an arena of its own and is not refcounted!?!? */ 1.764 + rv = NSS_CMSArray_Add(sigd->cmsg->poolp, (void ***)&(sigd->certLists), (void *)certlist); 1.765 + 1.766 + return rv; 1.767 +} 1.768 + 1.769 +/* 1.770 + * NSS_CMSSignedData_AddCertChain - add cert and its entire chain to the set of certs 1.771 + */ 1.772 +SECStatus 1.773 +NSS_CMSSignedData_AddCertChain(NSSCMSSignedData *sigd, CERTCertificate *cert) 1.774 +{ 1.775 + CERTCertificateList *certlist; 1.776 + SECCertUsage usage; 1.777 + SECStatus rv; 1.778 + 1.779 + usage = certUsageEmailSigner; 1.780 + 1.781 + if (!sigd || !cert) { 1.782 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.783 + return SECFailure; 1.784 + } 1.785 + 1.786 + /* do not include root */ 1.787 + certlist = CERT_CertChainFromCert(cert, usage, PR_FALSE); 1.788 + if (certlist == NULL) 1.789 + return SECFailure; 1.790 + 1.791 + rv = NSS_CMSSignedData_AddCertList(sigd, certlist); 1.792 + 1.793 + return rv; 1.794 +} 1.795 + 1.796 +extern SECStatus 1.797 +NSS_CMSSignedData_AddTempCertificate(NSSCMSSignedData *sigd, CERTCertificate *cert) 1.798 +{ 1.799 + CERTCertificate *c; 1.800 + SECStatus rv; 1.801 + 1.802 + if (!sigd || !cert) { 1.803 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.804 + return SECFailure; 1.805 + } 1.806 + 1.807 + c = CERT_DupCertificate(cert); 1.808 + rv = NSS_CMSArray_Add(sigd->cmsg->poolp, (void ***)&(sigd->tempCerts), (void *)c); 1.809 + return rv; 1.810 +} 1.811 + 1.812 +SECStatus 1.813 +NSS_CMSSignedData_AddCertificate(NSSCMSSignedData *sigd, CERTCertificate *cert) 1.814 +{ 1.815 + CERTCertificate *c; 1.816 + SECStatus rv; 1.817 + 1.818 + if (!sigd || !cert) { 1.819 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.820 + return SECFailure; 1.821 + } 1.822 + 1.823 + c = CERT_DupCertificate(cert); 1.824 + rv = NSS_CMSArray_Add(sigd->cmsg->poolp, (void ***)&(sigd->certs), (void *)c); 1.825 + return rv; 1.826 +} 1.827 + 1.828 +PRBool 1.829 +NSS_CMSSignedData_ContainsCertsOrCrls(NSSCMSSignedData *sigd) 1.830 +{ 1.831 + if (!sigd) { 1.832 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.833 + return PR_FALSE; 1.834 + } 1.835 + if (sigd->rawCerts != NULL && sigd->rawCerts[0] != NULL) 1.836 + return PR_TRUE; 1.837 + else if (sigd->crls != NULL && sigd->crls[0] != NULL) 1.838 + return PR_TRUE; 1.839 + else 1.840 + return PR_FALSE; 1.841 +} 1.842 + 1.843 +SECStatus 1.844 +NSS_CMSSignedData_AddSignerInfo(NSSCMSSignedData *sigd, 1.845 + NSSCMSSignerInfo *signerinfo) 1.846 +{ 1.847 + void *mark; 1.848 + SECStatus rv; 1.849 + SECOidTag digestalgtag; 1.850 + PLArenaPool *poolp; 1.851 + 1.852 + if (!sigd || !signerinfo) { 1.853 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.854 + return SECFailure; 1.855 + } 1.856 + 1.857 + poolp = sigd->cmsg->poolp; 1.858 + 1.859 + mark = PORT_ArenaMark(poolp); 1.860 + 1.861 + /* add signerinfo */ 1.862 + rv = NSS_CMSArray_Add(poolp, (void ***)&(sigd->signerInfos), (void *)signerinfo); 1.863 + if (rv != SECSuccess) 1.864 + goto loser; 1.865 + 1.866 + /* 1.867 + * add empty digest 1.868 + * Empty because we don't have it yet. Either it gets created during encoding 1.869 + * (if the data is present) or has to be set externally. 1.870 + * XXX maybe pass it in optionally? 1.871 + */ 1.872 + digestalgtag = NSS_CMSSignerInfo_GetDigestAlgTag(signerinfo); 1.873 + rv = NSS_CMSSignedData_SetDigestValue(sigd, digestalgtag, NULL); 1.874 + if (rv != SECSuccess) 1.875 + goto loser; 1.876 + 1.877 + /* 1.878 + * The last thing to get consistency would be adding the digest. 1.879 + */ 1.880 + 1.881 + PORT_ArenaUnmark(poolp, mark); 1.882 + return SECSuccess; 1.883 + 1.884 +loser: 1.885 + PORT_ArenaRelease (poolp, mark); 1.886 + return SECFailure; 1.887 +} 1.888 + 1.889 +/* 1.890 + * NSS_CMSSignedData_SetDigests - set a signedData's digests member 1.891 + * 1.892 + * "digestalgs" - array of digest algorithm IDs 1.893 + * "digests" - array of digests corresponding to the digest algorithms 1.894 + */ 1.895 +SECStatus 1.896 +NSS_CMSSignedData_SetDigests(NSSCMSSignedData *sigd, 1.897 + SECAlgorithmID **digestalgs, 1.898 + SECItem **digests) 1.899 +{ 1.900 + int cnt, i, idx; 1.901 + 1.902 + if (!sigd || !digestalgs || !digests) { 1.903 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.904 + return SECFailure; 1.905 + } 1.906 + 1.907 + if (sigd->digestAlgorithms == NULL) { 1.908 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.909 + return SECFailure; 1.910 + } 1.911 + 1.912 + /* we assume that the digests array is just not there yet */ 1.913 + PORT_Assert(sigd->digests == NULL); 1.914 + if (sigd->digests != NULL) { 1.915 + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1.916 + return SECFailure; 1.917 + } 1.918 + 1.919 + /* now allocate one (same size as digestAlgorithms) */ 1.920 + cnt = NSS_CMSArray_Count((void **)sigd->digestAlgorithms); 1.921 + sigd->digests = PORT_ArenaZAlloc(sigd->cmsg->poolp, (cnt + 1) * sizeof(SECItem *)); 1.922 + if (sigd->digests == NULL) { 1.923 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.924 + return SECFailure; 1.925 + } 1.926 + 1.927 + for (i = 0; sigd->digestAlgorithms[i] != NULL; i++) { 1.928 + /* try to find the sigd's i'th digest algorithm in the array we passed in */ 1.929 + idx = NSS_CMSAlgArray_GetIndexByAlgID(digestalgs, sigd->digestAlgorithms[i]); 1.930 + if (idx < 0) { 1.931 + PORT_SetError(SEC_ERROR_DIGEST_NOT_FOUND); 1.932 + return SECFailure; 1.933 + } 1.934 + if (!digests[idx]) { 1.935 + /* We have no digest for this algorithm, probably because it is 1.936 + ** unrecognized or unsupported. We'll ignore this here. If this 1.937 + ** digest is needed later, an error will be be generated then. 1.938 + */ 1.939 + continue; 1.940 + } 1.941 + 1.942 + /* found it - now set it */ 1.943 + if ((sigd->digests[i] = SECITEM_AllocItem(sigd->cmsg->poolp, NULL, 0)) == NULL || 1.944 + SECITEM_CopyItem(sigd->cmsg->poolp, sigd->digests[i], digests[idx]) != SECSuccess) 1.945 + { 1.946 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.947 + return SECFailure; 1.948 + } 1.949 + } 1.950 + return SECSuccess; 1.951 +} 1.952 + 1.953 +SECStatus 1.954 +NSS_CMSSignedData_SetDigestValue(NSSCMSSignedData *sigd, 1.955 + SECOidTag digestalgtag, 1.956 + SECItem *digestdata) 1.957 +{ 1.958 + SECItem *digest = NULL; 1.959 + PLArenaPool *poolp; 1.960 + void *mark; 1.961 + int n, cnt; 1.962 + 1.963 + if (!sigd) { 1.964 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.965 + return SECFailure; 1.966 + } 1.967 + 1.968 + poolp = sigd->cmsg->poolp; 1.969 + 1.970 + mark = PORT_ArenaMark(poolp); 1.971 + 1.972 + 1.973 + if (digestdata) { 1.974 + digest = (SECItem *) PORT_ArenaZAlloc(poolp,sizeof(SECItem)); 1.975 + 1.976 + /* copy digestdata item to arena (in case we have it and are not only making room) */ 1.977 + if (SECITEM_CopyItem(poolp, digest, digestdata) != SECSuccess) 1.978 + goto loser; 1.979 + } 1.980 + 1.981 + /* now allocate one (same size as digestAlgorithms) */ 1.982 + if (sigd->digests == NULL) { 1.983 + cnt = NSS_CMSArray_Count((void **)sigd->digestAlgorithms); 1.984 + sigd->digests = PORT_ArenaZAlloc(sigd->cmsg->poolp, (cnt + 1) * sizeof(SECItem *)); 1.985 + if (sigd->digests == NULL) { 1.986 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.987 + return SECFailure; 1.988 + } 1.989 + } 1.990 + 1.991 + n = -1; 1.992 + if (sigd->digestAlgorithms != NULL) 1.993 + n = NSS_CMSAlgArray_GetIndexByAlgTag(sigd->digestAlgorithms, digestalgtag); 1.994 + 1.995 + /* if not found, add a digest */ 1.996 + if (n < 0) { 1.997 + if (NSS_CMSSignedData_AddDigest(poolp, sigd, digestalgtag, digest) != SECSuccess) 1.998 + goto loser; 1.999 + } else { 1.1000 + /* replace NULL pointer with digest item (and leak previous value) */ 1.1001 + sigd->digests[n] = digest; 1.1002 + } 1.1003 + 1.1004 + PORT_ArenaUnmark(poolp, mark); 1.1005 + return SECSuccess; 1.1006 + 1.1007 +loser: 1.1008 + PORT_ArenaRelease(poolp, mark); 1.1009 + return SECFailure; 1.1010 +} 1.1011 + 1.1012 +SECStatus 1.1013 +NSS_CMSSignedData_AddDigest(PLArenaPool *poolp, 1.1014 + NSSCMSSignedData *sigd, 1.1015 + SECOidTag digestalgtag, 1.1016 + SECItem *digest) 1.1017 +{ 1.1018 + SECAlgorithmID *digestalg; 1.1019 + void *mark; 1.1020 + 1.1021 + if (!sigd || !poolp) { 1.1022 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.1023 + return SECFailure; 1.1024 + } 1.1025 + 1.1026 + mark = PORT_ArenaMark(poolp); 1.1027 + 1.1028 + digestalg = PORT_ArenaZAlloc(poolp, sizeof(SECAlgorithmID)); 1.1029 + if (digestalg == NULL) 1.1030 + goto loser; 1.1031 + 1.1032 + if (SECOID_SetAlgorithmID (poolp, digestalg, digestalgtag, NULL) != SECSuccess) /* no params */ 1.1033 + goto loser; 1.1034 + 1.1035 + if (NSS_CMSArray_Add(poolp, (void ***)&(sigd->digestAlgorithms), (void *)digestalg) != SECSuccess || 1.1036 + /* even if digest is NULL, add dummy to have same-size array */ 1.1037 + NSS_CMSArray_Add(poolp, (void ***)&(sigd->digests), (void *)digest) != SECSuccess) 1.1038 + { 1.1039 + goto loser; 1.1040 + } 1.1041 + 1.1042 + PORT_ArenaUnmark(poolp, mark); 1.1043 + return SECSuccess; 1.1044 + 1.1045 +loser: 1.1046 + PORT_ArenaRelease(poolp, mark); 1.1047 + return SECFailure; 1.1048 +} 1.1049 + 1.1050 +/* XXX This function doesn't set the error code on failure. */ 1.1051 +SECItem * 1.1052 +NSS_CMSSignedData_GetDigestValue(NSSCMSSignedData *sigd, SECOidTag digestalgtag) 1.1053 +{ 1.1054 + int n; 1.1055 + 1.1056 + if (!sigd) { 1.1057 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.1058 + return NULL; 1.1059 + } 1.1060 + 1.1061 + if (sigd->digestAlgorithms == NULL || sigd->digests == NULL) { 1.1062 + PORT_SetError(SEC_ERROR_DIGEST_NOT_FOUND); 1.1063 + return NULL; 1.1064 + } 1.1065 + 1.1066 + n = NSS_CMSAlgArray_GetIndexByAlgTag(sigd->digestAlgorithms, digestalgtag); 1.1067 + 1.1068 + return (n < 0) ? NULL : sigd->digests[n]; 1.1069 +} 1.1070 + 1.1071 +/* ============================================================================= 1.1072 + * Misc. utility functions 1.1073 + */ 1.1074 + 1.1075 +/* 1.1076 + * NSS_CMSSignedData_CreateCertsOnly - create a certs-only SignedData. 1.1077 + * 1.1078 + * cert - base certificates that will be included 1.1079 + * include_chain - if true, include the complete cert chain for cert 1.1080 + * 1.1081 + * More certs and chains can be added via AddCertificate and AddCertChain. 1.1082 + * 1.1083 + * An error results in a return value of NULL and an error set. 1.1084 + * 1.1085 + * XXXX CRLs 1.1086 + */ 1.1087 +NSSCMSSignedData * 1.1088 +NSS_CMSSignedData_CreateCertsOnly(NSSCMSMessage *cmsg, CERTCertificate *cert, PRBool include_chain) 1.1089 +{ 1.1090 + NSSCMSSignedData *sigd; 1.1091 + void *mark; 1.1092 + PLArenaPool *poolp; 1.1093 + SECStatus rv; 1.1094 + 1.1095 + if (!cmsg || !cert) { 1.1096 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.1097 + return NULL; 1.1098 + } 1.1099 + 1.1100 + poolp = cmsg->poolp; 1.1101 + mark = PORT_ArenaMark(poolp); 1.1102 + 1.1103 + sigd = NSS_CMSSignedData_Create(cmsg); 1.1104 + if (sigd == NULL) 1.1105 + goto loser; 1.1106 + 1.1107 + /* no signerinfos, thus no digestAlgorithms */ 1.1108 + 1.1109 + /* but certs */ 1.1110 + if (include_chain) { 1.1111 + rv = NSS_CMSSignedData_AddCertChain(sigd, cert); 1.1112 + } else { 1.1113 + rv = NSS_CMSSignedData_AddCertificate(sigd, cert); 1.1114 + } 1.1115 + if (rv != SECSuccess) 1.1116 + goto loser; 1.1117 + 1.1118 + /* RFC2630 5.2 sez: 1.1119 + * In the degenerate case where there are no signers, the 1.1120 + * EncapsulatedContentInfo value being "signed" is irrelevant. In this 1.1121 + * case, the content type within the EncapsulatedContentInfo value being 1.1122 + * "signed" should be id-data (as defined in section 4), and the content 1.1123 + * field of the EncapsulatedContentInfo value should be omitted. 1.1124 + */ 1.1125 + rv = NSS_CMSContentInfo_SetContent_Data(cmsg, &(sigd->contentInfo), NULL, PR_TRUE); 1.1126 + if (rv != SECSuccess) 1.1127 + goto loser; 1.1128 + 1.1129 + PORT_ArenaUnmark(poolp, mark); 1.1130 + return sigd; 1.1131 + 1.1132 +loser: 1.1133 + if (sigd) 1.1134 + NSS_CMSSignedData_Destroy(sigd); 1.1135 + PORT_ArenaRelease(poolp, mark); 1.1136 + return NULL; 1.1137 +} 1.1138 + 1.1139 +/* TODO: 1.1140 + * NSS_CMSSignerInfo_GetReceiptRequest() 1.1141 + * NSS_CMSSignedData_HasReceiptRequest() 1.1142 + * easy way to iterate over signers 1.1143 + */ 1.1144 +