cmscinfo.c (12254B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /* 6 * CMS contentInfo methods. 7 */ 8 9 #include "cmslocal.h" 10 11 #include "pk11func.h" 12 #include "secitem.h" 13 #include "secoid.h" 14 #include "secerr.h" 15 16 /* 17 * NSS_CMSContentInfo_Create - create a content info 18 * 19 * version is set in the _Finalize procedures for each content type 20 */ 21 SECStatus 22 NSS_CMSContentInfo_Private_Init(NSSCMSContentInfo *cinfo) 23 { 24 if (cinfo->privateInfo) { 25 return SECSuccess; 26 } 27 cinfo->privateInfo = PORT_ZNew(NSSCMSContentInfoPrivate); 28 return (cinfo->privateInfo) ? SECSuccess : SECFailure; 29 } 30 31 static void 32 nss_cmsContentInfo_private_destroy(NSSCMSContentInfoPrivate *privateInfo) 33 { 34 if (privateInfo->digcx) { 35 /* must destroy digest objects */ 36 NSS_CMSDigestContext_Cancel(privateInfo->digcx); 37 privateInfo->digcx = NULL; 38 } 39 if (privateInfo->ciphcx) { 40 NSS_CMSCipherContext_Destroy(privateInfo->ciphcx); 41 privateInfo->ciphcx = NULL; 42 } 43 PORT_Free(privateInfo); 44 } 45 46 /* 47 * NSS_CMSContentInfo_Destroy - destroy a CMS contentInfo and all of its sub-pieces. 48 */ 49 void 50 NSS_CMSContentInfo_Destroy(NSSCMSContentInfo *cinfo) 51 { 52 SECOidTag kind; 53 54 if (cinfo == NULL) { 55 return; 56 } 57 58 kind = NSS_CMSContentInfo_GetContentTypeTag(cinfo); 59 switch (kind) { 60 case SEC_OID_PKCS7_ENVELOPED_DATA: 61 NSS_CMSEnvelopedData_Destroy(cinfo->content.envelopedData); 62 break; 63 case SEC_OID_PKCS7_SIGNED_DATA: 64 NSS_CMSSignedData_Destroy(cinfo->content.signedData); 65 break; 66 case SEC_OID_PKCS7_ENCRYPTED_DATA: 67 NSS_CMSEncryptedData_Destroy(cinfo->content.encryptedData); 68 break; 69 case SEC_OID_PKCS7_DIGESTED_DATA: 70 NSS_CMSDigestedData_Destroy(cinfo->content.digestedData); 71 break; 72 default: 73 NSS_CMSGenericWrapperData_Destroy(kind, cinfo->content.genericData); 74 /* XXX Anything else that needs to be "manually" freed/destroyed? */ 75 break; 76 } 77 if (cinfo->privateInfo) { 78 nss_cmsContentInfo_private_destroy(cinfo->privateInfo); 79 cinfo->privateInfo = NULL; 80 } 81 if (cinfo->bulkkey) { 82 PK11_FreeSymKey(cinfo->bulkkey); 83 } 84 } 85 86 /* 87 * NSS_CMSContentInfo_GetChildContentInfo - get content's contentInfo (if it exists) 88 */ 89 NSSCMSContentInfo * 90 NSS_CMSContentInfo_GetChildContentInfo(NSSCMSContentInfo *cinfo) 91 { 92 NSSCMSContentInfo *ccinfo = NULL; 93 94 if (cinfo == NULL) { 95 return NULL; 96 } 97 98 SECOidTag tag = NSS_CMSContentInfo_GetContentTypeTag(cinfo); 99 switch (tag) { 100 case SEC_OID_PKCS7_SIGNED_DATA: 101 if (cinfo->content.signedData != NULL) { 102 ccinfo = &(cinfo->content.signedData->contentInfo); 103 } 104 break; 105 case SEC_OID_PKCS7_ENVELOPED_DATA: 106 if (cinfo->content.envelopedData != NULL) { 107 ccinfo = &(cinfo->content.envelopedData->contentInfo); 108 } 109 break; 110 case SEC_OID_PKCS7_DIGESTED_DATA: 111 if (cinfo->content.digestedData != NULL) { 112 ccinfo = &(cinfo->content.digestedData->contentInfo); 113 } 114 break; 115 case SEC_OID_PKCS7_ENCRYPTED_DATA: 116 if (cinfo->content.encryptedData != NULL) { 117 ccinfo = &(cinfo->content.encryptedData->contentInfo); 118 } 119 break; 120 case SEC_OID_PKCS7_DATA: 121 default: 122 if (NSS_CMSType_IsWrapper(tag)) { 123 if (cinfo->content.genericData != NULL) { 124 ccinfo = &(cinfo->content.genericData->contentInfo); 125 } 126 } 127 break; 128 } 129 if (ccinfo && !ccinfo->privateInfo) { 130 NSS_CMSContentInfo_Private_Init(ccinfo); 131 } 132 return ccinfo; 133 } 134 135 SECStatus 136 NSS_CMSContentInfo_SetDontStream(NSSCMSContentInfo *cinfo, PRBool dontStream) 137 { 138 SECStatus rv; 139 if (cinfo == NULL) { 140 return SECFailure; 141 } 142 143 rv = NSS_CMSContentInfo_Private_Init(cinfo); 144 if (rv != SECSuccess) { 145 /* default is streaming, failure to get ccinfo will not effect this */ 146 return dontStream ? SECFailure : SECSuccess; 147 } 148 cinfo->privateInfo->dontStream = dontStream; 149 return SECSuccess; 150 } 151 152 /* 153 * NSS_CMSContentInfo_SetContent - set content type & content 154 */ 155 SECStatus 156 NSS_CMSContentInfo_SetContent(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo, 157 SECOidTag type, void *ptr) 158 { 159 SECStatus rv; 160 if (cinfo == NULL || cmsg == NULL) { 161 return SECFailure; 162 } 163 164 cinfo->contentTypeTag = SECOID_FindOIDByTag(type); 165 if (cinfo->contentTypeTag == NULL) { 166 return SECFailure; 167 } 168 169 /* do not copy the oid, just create a reference */ 170 rv = SECITEM_CopyItem(cmsg->poolp, &(cinfo->contentType), &(cinfo->contentTypeTag->oid)); 171 if (rv != SECSuccess) { 172 return SECFailure; 173 } 174 175 cinfo->content.pointer = ptr; 176 177 if (NSS_CMSType_IsData(type) && ptr) { 178 cinfo->rawContent = ptr; 179 } else { 180 /* as we always have some inner data, 181 * we need to set it to something, just to fool the encoder enough to work on it 182 * and get us into nss_cms_encoder_notify at that point */ 183 cinfo->rawContent = SECITEM_AllocItem(cmsg->poolp, NULL, 1); 184 if (cinfo->rawContent == NULL) { 185 PORT_SetError(SEC_ERROR_NO_MEMORY); 186 return SECFailure; 187 } 188 } 189 190 return SECSuccess; 191 } 192 193 /* 194 * NSS_CMSContentInfo_SetContent_XXXX - typesafe wrappers for NSS_CMSContentInfo_SetContent 195 */ 196 197 /* 198 * data == NULL -> pass in data via NSS_CMSEncoder_Update 199 * data != NULL -> take this data 200 */ 201 SECStatus 202 NSS_CMSContentInfo_SetContent_Data(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo, 203 SECItem *data, PRBool detached) 204 { 205 if (NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_DATA, (void *)data) != SECSuccess) { 206 return SECFailure; 207 } 208 if (detached) { 209 cinfo->rawContent = NULL; 210 } 211 212 return SECSuccess; 213 } 214 215 SECStatus 216 NSS_CMSContentInfo_SetContent_SignedData(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo, 217 NSSCMSSignedData *sigd) 218 { 219 return NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_SIGNED_DATA, (void *)sigd); 220 } 221 222 SECStatus 223 NSS_CMSContentInfo_SetContent_EnvelopedData(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo, 224 NSSCMSEnvelopedData *envd) 225 { 226 return NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_ENVELOPED_DATA, (void *)envd); 227 } 228 229 SECStatus 230 NSS_CMSContentInfo_SetContent_DigestedData(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo, 231 NSSCMSDigestedData *digd) 232 { 233 return NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_DIGESTED_DATA, (void *)digd); 234 } 235 236 SECStatus 237 NSS_CMSContentInfo_SetContent_EncryptedData(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo, 238 NSSCMSEncryptedData *encd) 239 { 240 return NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_ENCRYPTED_DATA, (void *)encd); 241 } 242 243 /* 244 * NSS_CMSContentInfo_GetContent - get pointer to inner content 245 * 246 * needs to be casted... 247 */ 248 void * 249 NSS_CMSContentInfo_GetContent(NSSCMSContentInfo *cinfo) 250 { 251 if (cinfo == NULL) { 252 return NULL; 253 } 254 255 SECOidTag tag = cinfo->contentTypeTag 256 ? cinfo->contentTypeTag->offset 257 : SEC_OID_UNKNOWN; 258 switch (tag) { 259 case SEC_OID_PKCS7_DATA: 260 case SEC_OID_PKCS7_SIGNED_DATA: 261 case SEC_OID_PKCS7_ENVELOPED_DATA: 262 case SEC_OID_PKCS7_DIGESTED_DATA: 263 case SEC_OID_PKCS7_ENCRYPTED_DATA: 264 return cinfo->content.pointer; 265 default: 266 return NSS_CMSType_IsWrapper(tag) ? cinfo->content.pointer 267 : (NSS_CMSType_IsData(tag) ? cinfo->rawContent 268 : NULL); 269 } 270 } 271 272 /* 273 * NSS_CMSContentInfo_GetInnerContent - get pointer to innermost content 274 * 275 * this is typically only called by NSS_CMSMessage_GetContent() 276 */ 277 278 SECItem * 279 NSS_CMSContentInfo_GetInnerContent(NSSCMSContentInfo *cinfo) 280 { 281 NSSCMSContentInfo *ccinfo; 282 SECOidTag tag; 283 SECItem *pItem = NULL; 284 285 if (cinfo == NULL) { 286 return NULL; 287 } 288 289 tag = NSS_CMSContentInfo_GetContentTypeTag(cinfo); 290 if (NSS_CMSType_IsData(tag)) { 291 pItem = cinfo->content.data; 292 } else if (NSS_CMSType_IsWrapper(tag)) { 293 ccinfo = NSS_CMSContentInfo_GetChildContentInfo(cinfo); 294 if (ccinfo != NULL) { 295 pItem = NSS_CMSContentInfo_GetContent(ccinfo); 296 } 297 } else { 298 PORT_Assert(0); 299 } 300 301 return pItem; 302 } 303 304 /* 305 * NSS_CMSContentInfo_GetContentType{Tag,OID} - find out (saving pointer to lookup result 306 * for future reference) and return the inner content type. 307 */ 308 SECOidTag 309 NSS_CMSContentInfo_GetContentTypeTag(NSSCMSContentInfo *cinfo) 310 { 311 if (cinfo == NULL) { 312 return SEC_OID_UNKNOWN; 313 } 314 315 if (cinfo->contentTypeTag == NULL) 316 cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType)); 317 318 if (cinfo->contentTypeTag == NULL) 319 return SEC_OID_UNKNOWN; 320 321 return cinfo->contentTypeTag->offset; 322 } 323 324 SECItem * 325 NSS_CMSContentInfo_GetContentTypeOID(NSSCMSContentInfo *cinfo) 326 { 327 if (cinfo == NULL) { 328 return NULL; 329 } 330 331 if (cinfo->contentTypeTag == NULL) { 332 cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType)); 333 } 334 335 if (cinfo->contentTypeTag == NULL) { 336 return NULL; 337 } 338 339 return &(cinfo->contentTypeTag->oid); 340 } 341 342 /* 343 * NSS_CMSContentInfo_GetContentEncAlgTag - find out (saving pointer to lookup result 344 * for future reference) and return the content encryption algorithm tag. 345 */ 346 SECOidTag 347 NSS_CMSContentInfo_GetContentEncAlgTag(NSSCMSContentInfo *cinfo) 348 { 349 if (cinfo == NULL) { 350 return SEC_OID_UNKNOWN; 351 } 352 353 if (cinfo->contentEncAlgTag == SEC_OID_UNKNOWN) { 354 cinfo->contentEncAlgTag = SECOID_GetAlgorithmTag(&(cinfo->contentEncAlg)); 355 } 356 357 return cinfo->contentEncAlgTag; 358 } 359 360 /* 361 * NSS_CMSContentInfo_GetContentEncAlg - find out and return the content encryption algorithm tag. 362 */ 363 SECAlgorithmID * 364 NSS_CMSContentInfo_GetContentEncAlg(NSSCMSContentInfo *cinfo) 365 { 366 if (cinfo == NULL) { 367 return NULL; 368 } 369 370 return &(cinfo->contentEncAlg); 371 } 372 373 SECStatus 374 NSS_CMSContentInfo_SetContentEncAlg(PLArenaPool *poolp, NSSCMSContentInfo *cinfo, 375 SECOidTag bulkalgtag, SECItem *parameters, int keysize) 376 { 377 SECStatus rv; 378 if (cinfo == NULL) { 379 return SECFailure; 380 } 381 382 rv = SECOID_SetAlgorithmID(poolp, &(cinfo->contentEncAlg), bulkalgtag, parameters); 383 if (rv != SECSuccess) { 384 return SECFailure; 385 } 386 cinfo->keysize = keysize; 387 return SECSuccess; 388 } 389 390 SECStatus 391 NSS_CMSContentInfo_SetContentEncAlgID(PLArenaPool *poolp, NSSCMSContentInfo *cinfo, 392 SECAlgorithmID *algid, int keysize) 393 { 394 SECStatus rv; 395 if (cinfo == NULL) { 396 return SECFailure; 397 } 398 399 rv = SECOID_CopyAlgorithmID(poolp, &(cinfo->contentEncAlg), algid); 400 if (rv != SECSuccess) { 401 return SECFailure; 402 } 403 if (keysize >= 0) { 404 cinfo->keysize = keysize; 405 } 406 return SECSuccess; 407 } 408 409 void 410 NSS_CMSContentInfo_SetBulkKey(NSSCMSContentInfo *cinfo, PK11SymKey *bulkkey) 411 { 412 if (cinfo == NULL) { 413 return; 414 } 415 416 if (bulkkey == NULL) { 417 cinfo->bulkkey = NULL; 418 cinfo->keysize = 0; 419 } else { 420 cinfo->bulkkey = PK11_ReferenceSymKey(bulkkey); 421 cinfo->keysize = PK11_GetKeyStrength(cinfo->bulkkey, &(cinfo->contentEncAlg)); 422 } 423 } 424 425 PK11SymKey * 426 NSS_CMSContentInfo_GetBulkKey(NSSCMSContentInfo *cinfo) 427 { 428 if (cinfo == NULL || cinfo->bulkkey == NULL) { 429 return NULL; 430 } 431 432 return PK11_ReferenceSymKey(cinfo->bulkkey); 433 } 434 435 int 436 NSS_CMSContentInfo_GetBulkKeySize(NSSCMSContentInfo *cinfo) 437 { 438 if (cinfo == NULL) { 439 return 0; 440 } 441 442 return cinfo->keysize; 443 }