1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/smime/cmscinfo.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,371 @@ 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 contentInfo methods. 1.10 + */ 1.11 + 1.12 +#include "cmslocal.h" 1.13 + 1.14 +#include "pk11func.h" 1.15 +#include "secitem.h" 1.16 +#include "secoid.h" 1.17 +#include "secerr.h" 1.18 + 1.19 + 1.20 +/* 1.21 + * NSS_CMSContentInfo_Create - create a content info 1.22 + * 1.23 + * version is set in the _Finalize procedures for each content type 1.24 + */ 1.25 +SECStatus 1.26 +NSS_CMSContentInfo_Private_Init(NSSCMSContentInfo *cinfo) 1.27 +{ 1.28 + if (cinfo->privateInfo) { 1.29 + return SECSuccess; 1.30 + } 1.31 + cinfo->privateInfo = PORT_ZNew(NSSCMSContentInfoPrivate); 1.32 + return (cinfo->privateInfo) ? SECSuccess : SECFailure; 1.33 +} 1.34 + 1.35 + 1.36 +static void 1.37 +nss_cmsContentInfo_private_destroy(NSSCMSContentInfoPrivate *privateInfo) 1.38 +{ 1.39 + if (privateInfo->digcx) { 1.40 + /* must destroy digest objects */ 1.41 + NSS_CMSDigestContext_Cancel(privateInfo->digcx); 1.42 + privateInfo->digcx = NULL; 1.43 + } 1.44 + if (privateInfo->ciphcx) { 1.45 + NSS_CMSCipherContext_Destroy(privateInfo->ciphcx); 1.46 + privateInfo->ciphcx = NULL; 1.47 + } 1.48 + PORT_Free(privateInfo); 1.49 +} 1.50 + 1.51 +/* 1.52 + * NSS_CMSContentInfo_Destroy - destroy a CMS contentInfo and all of its sub-pieces. 1.53 + */ 1.54 +void 1.55 +NSS_CMSContentInfo_Destroy(NSSCMSContentInfo *cinfo) 1.56 +{ 1.57 + SECOidTag kind; 1.58 + 1.59 + kind = NSS_CMSContentInfo_GetContentTypeTag(cinfo); 1.60 + switch (kind) { 1.61 + case SEC_OID_PKCS7_ENVELOPED_DATA: 1.62 + NSS_CMSEnvelopedData_Destroy(cinfo->content.envelopedData); 1.63 + break; 1.64 + case SEC_OID_PKCS7_SIGNED_DATA: 1.65 + NSS_CMSSignedData_Destroy(cinfo->content.signedData); 1.66 + break; 1.67 + case SEC_OID_PKCS7_ENCRYPTED_DATA: 1.68 + NSS_CMSEncryptedData_Destroy(cinfo->content.encryptedData); 1.69 + break; 1.70 + case SEC_OID_PKCS7_DIGESTED_DATA: 1.71 + NSS_CMSDigestedData_Destroy(cinfo->content.digestedData); 1.72 + break; 1.73 + default: 1.74 + NSS_CMSGenericWrapperData_Destroy(kind, cinfo->content.genericData); 1.75 + /* XXX Anything else that needs to be "manually" freed/destroyed? */ 1.76 + break; 1.77 + } 1.78 + if (cinfo->privateInfo) { 1.79 + nss_cmsContentInfo_private_destroy(cinfo->privateInfo); 1.80 + cinfo->privateInfo = NULL; 1.81 + } 1.82 + if (cinfo->bulkkey) { 1.83 + PK11_FreeSymKey(cinfo->bulkkey); 1.84 + } 1.85 +} 1.86 + 1.87 +/* 1.88 + * NSS_CMSContentInfo_GetChildContentInfo - get content's contentInfo (if it exists) 1.89 + */ 1.90 +NSSCMSContentInfo * 1.91 +NSS_CMSContentInfo_GetChildContentInfo(NSSCMSContentInfo *cinfo) 1.92 +{ 1.93 + NSSCMSContentInfo * ccinfo = NULL; 1.94 + SECOidTag tag = NSS_CMSContentInfo_GetContentTypeTag(cinfo); 1.95 + switch (tag) { 1.96 + case SEC_OID_PKCS7_SIGNED_DATA: 1.97 + if (cinfo->content.signedData != NULL) { 1.98 + ccinfo = &(cinfo->content.signedData->contentInfo); 1.99 + } 1.100 + break; 1.101 + case SEC_OID_PKCS7_ENVELOPED_DATA: 1.102 + if (cinfo->content.envelopedData != NULL) { 1.103 + ccinfo = &(cinfo->content.envelopedData->contentInfo); 1.104 + } 1.105 + break; 1.106 + case SEC_OID_PKCS7_DIGESTED_DATA: 1.107 + if (cinfo->content.digestedData != NULL) { 1.108 + ccinfo = &(cinfo->content.digestedData->contentInfo); 1.109 + } 1.110 + break; 1.111 + case SEC_OID_PKCS7_ENCRYPTED_DATA: 1.112 + if (cinfo->content.encryptedData != NULL) { 1.113 + ccinfo = &(cinfo->content.encryptedData->contentInfo); 1.114 + } 1.115 + break; 1.116 + case SEC_OID_PKCS7_DATA: 1.117 + default: 1.118 + if (NSS_CMSType_IsWrapper(tag)) { 1.119 + if (cinfo->content.genericData != NULL) { 1.120 + ccinfo = &(cinfo->content.genericData->contentInfo); 1.121 + } 1.122 + } 1.123 + break; 1.124 + } 1.125 + if (ccinfo && !ccinfo->privateInfo) { 1.126 + NSS_CMSContentInfo_Private_Init(ccinfo); 1.127 + } 1.128 + return ccinfo; 1.129 +} 1.130 + 1.131 +SECStatus 1.132 +NSS_CMSContentInfo_SetDontStream(NSSCMSContentInfo *cinfo, PRBool dontStream) 1.133 +{ 1.134 + SECStatus rv; 1.135 + 1.136 + rv = NSS_CMSContentInfo_Private_Init(cinfo); 1.137 + if (rv != SECSuccess) { 1.138 + /* default is streaming, failure to get ccinfo will not effect this */ 1.139 + return dontStream ? SECFailure : SECSuccess ; 1.140 + } 1.141 + cinfo->privateInfo->dontStream = dontStream; 1.142 + return SECSuccess; 1.143 +} 1.144 + 1.145 +/* 1.146 + * NSS_CMSContentInfo_SetContent - set content type & content 1.147 + */ 1.148 +SECStatus 1.149 +NSS_CMSContentInfo_SetContent(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo, SECOidTag type, void *ptr) 1.150 +{ 1.151 + SECStatus rv; 1.152 + 1.153 + cinfo->contentTypeTag = SECOID_FindOIDByTag(type); 1.154 + if (cinfo->contentTypeTag == NULL) 1.155 + return SECFailure; 1.156 + 1.157 + /* do not copy the oid, just create a reference */ 1.158 + rv = SECITEM_CopyItem (cmsg->poolp, &(cinfo->contentType), &(cinfo->contentTypeTag->oid)); 1.159 + if (rv != SECSuccess) 1.160 + return SECFailure; 1.161 + 1.162 + cinfo->content.pointer = ptr; 1.163 + 1.164 + if (NSS_CMSType_IsData(type) && ptr) { 1.165 + cinfo->rawContent = ptr; 1.166 + } else { 1.167 + /* as we always have some inner data, 1.168 + * we need to set it to something, just to fool the encoder enough to work on it 1.169 + * and get us into nss_cms_encoder_notify at that point */ 1.170 + cinfo->rawContent = SECITEM_AllocItem(cmsg->poolp, NULL, 1); 1.171 + if (cinfo->rawContent == NULL) { 1.172 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.173 + return SECFailure; 1.174 + } 1.175 + } 1.176 + 1.177 + return SECSuccess; 1.178 +} 1.179 + 1.180 +/* 1.181 + * NSS_CMSContentInfo_SetContent_XXXX - typesafe wrappers for NSS_CMSContentInfo_SetContent 1.182 + */ 1.183 + 1.184 +/* 1.185 + * data == NULL -> pass in data via NSS_CMSEncoder_Update 1.186 + * data != NULL -> take this data 1.187 + */ 1.188 +SECStatus 1.189 +NSS_CMSContentInfo_SetContent_Data(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo, SECItem *data, PRBool detached) 1.190 +{ 1.191 + if (NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_DATA, (void *)data) != SECSuccess) 1.192 + return SECFailure; 1.193 + if (detached) { 1.194 + cinfo->rawContent = NULL; 1.195 + } 1.196 + 1.197 + return SECSuccess; 1.198 +} 1.199 + 1.200 +SECStatus 1.201 +NSS_CMSContentInfo_SetContent_SignedData(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo, NSSCMSSignedData *sigd) 1.202 +{ 1.203 + return NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_SIGNED_DATA, (void *)sigd); 1.204 +} 1.205 + 1.206 +SECStatus 1.207 +NSS_CMSContentInfo_SetContent_EnvelopedData(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo, NSSCMSEnvelopedData *envd) 1.208 +{ 1.209 + return NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_ENVELOPED_DATA, (void *)envd); 1.210 +} 1.211 + 1.212 +SECStatus 1.213 +NSS_CMSContentInfo_SetContent_DigestedData(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo, NSSCMSDigestedData *digd) 1.214 +{ 1.215 + return NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_DIGESTED_DATA, (void *)digd); 1.216 +} 1.217 + 1.218 +SECStatus 1.219 +NSS_CMSContentInfo_SetContent_EncryptedData(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo, NSSCMSEncryptedData *encd) 1.220 +{ 1.221 + return NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_ENCRYPTED_DATA, (void *)encd); 1.222 +} 1.223 + 1.224 + 1.225 +/* 1.226 + * NSS_CMSContentInfo_GetContent - get pointer to inner content 1.227 + * 1.228 + * needs to be casted... 1.229 + */ 1.230 +void * 1.231 +NSS_CMSContentInfo_GetContent(NSSCMSContentInfo *cinfo) 1.232 +{ 1.233 + SECOidTag tag = (cinfo && cinfo->contentTypeTag) 1.234 + ? cinfo->contentTypeTag->offset 1.235 + : SEC_OID_UNKNOWN; 1.236 + switch (tag) { 1.237 + case SEC_OID_PKCS7_DATA: 1.238 + case SEC_OID_PKCS7_SIGNED_DATA: 1.239 + case SEC_OID_PKCS7_ENVELOPED_DATA: 1.240 + case SEC_OID_PKCS7_DIGESTED_DATA: 1.241 + case SEC_OID_PKCS7_ENCRYPTED_DATA: 1.242 + return cinfo->content.pointer; 1.243 + default: 1.244 + return NSS_CMSType_IsWrapper(tag) ? cinfo->content.pointer : (NSS_CMSType_IsData(tag) ? cinfo->rawContent : NULL); 1.245 + } 1.246 +} 1.247 + 1.248 +/* 1.249 + * NSS_CMSContentInfo_GetInnerContent - get pointer to innermost content 1.250 + * 1.251 + * this is typically only called by NSS_CMSMessage_GetContent() 1.252 + */ 1.253 + 1.254 +SECItem * 1.255 +NSS_CMSContentInfo_GetInnerContent(NSSCMSContentInfo *cinfo) 1.256 +{ 1.257 + NSSCMSContentInfo *ccinfo; 1.258 + SECOidTag tag; 1.259 + SECItem *pItem = NULL; 1.260 + 1.261 + tag = NSS_CMSContentInfo_GetContentTypeTag(cinfo); 1.262 + if (NSS_CMSType_IsData(tag)) { 1.263 + pItem = cinfo->content.data; 1.264 + } else if (NSS_CMSType_IsWrapper(tag)) { 1.265 + ccinfo = NSS_CMSContentInfo_GetChildContentInfo(cinfo); 1.266 + if (ccinfo != NULL) { 1.267 + pItem = NSS_CMSContentInfo_GetContent(ccinfo); 1.268 + } 1.269 + } else { 1.270 + PORT_Assert(0); 1.271 + } 1.272 + 1.273 + return pItem; 1.274 +} 1.275 + 1.276 + 1.277 +/* 1.278 + * NSS_CMSContentInfo_GetContentType{Tag,OID} - find out (saving pointer to lookup result 1.279 + * for future reference) and return the inner content type. 1.280 + */ 1.281 +SECOidTag 1.282 +NSS_CMSContentInfo_GetContentTypeTag(NSSCMSContentInfo *cinfo) 1.283 +{ 1.284 + if (cinfo->contentTypeTag == NULL) 1.285 + cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType)); 1.286 + 1.287 + if (cinfo->contentTypeTag == NULL) 1.288 + return SEC_OID_UNKNOWN; 1.289 + 1.290 + return cinfo->contentTypeTag->offset; 1.291 +} 1.292 + 1.293 +SECItem * 1.294 +NSS_CMSContentInfo_GetContentTypeOID(NSSCMSContentInfo *cinfo) 1.295 +{ 1.296 + if (cinfo->contentTypeTag == NULL) 1.297 + cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType)); 1.298 + 1.299 + if (cinfo->contentTypeTag == NULL) 1.300 + return NULL; 1.301 + 1.302 + return &(cinfo->contentTypeTag->oid); 1.303 +} 1.304 + 1.305 +/* 1.306 + * NSS_CMSContentInfo_GetContentEncAlgTag - find out (saving pointer to lookup result 1.307 + * for future reference) and return the content encryption algorithm tag. 1.308 + */ 1.309 +SECOidTag 1.310 +NSS_CMSContentInfo_GetContentEncAlgTag(NSSCMSContentInfo *cinfo) 1.311 +{ 1.312 + if (cinfo->contentEncAlgTag == SEC_OID_UNKNOWN) 1.313 + cinfo->contentEncAlgTag = SECOID_GetAlgorithmTag(&(cinfo->contentEncAlg)); 1.314 + 1.315 + return cinfo->contentEncAlgTag; 1.316 +} 1.317 + 1.318 +/* 1.319 + * NSS_CMSContentInfo_GetContentEncAlg - find out and return the content encryption algorithm tag. 1.320 + */ 1.321 +SECAlgorithmID * 1.322 +NSS_CMSContentInfo_GetContentEncAlg(NSSCMSContentInfo *cinfo) 1.323 +{ 1.324 + return &(cinfo->contentEncAlg); 1.325 +} 1.326 + 1.327 +SECStatus 1.328 +NSS_CMSContentInfo_SetContentEncAlg(PLArenaPool *poolp, NSSCMSContentInfo *cinfo, 1.329 + SECOidTag bulkalgtag, SECItem *parameters, int keysize) 1.330 +{ 1.331 + SECStatus rv; 1.332 + 1.333 + rv = SECOID_SetAlgorithmID(poolp, &(cinfo->contentEncAlg), bulkalgtag, parameters); 1.334 + if (rv != SECSuccess) 1.335 + return SECFailure; 1.336 + cinfo->keysize = keysize; 1.337 + return SECSuccess; 1.338 +} 1.339 + 1.340 +SECStatus 1.341 +NSS_CMSContentInfo_SetContentEncAlgID(PLArenaPool *poolp, NSSCMSContentInfo *cinfo, 1.342 + SECAlgorithmID *algid, int keysize) 1.343 +{ 1.344 + SECStatus rv; 1.345 + 1.346 + rv = SECOID_CopyAlgorithmID(poolp, &(cinfo->contentEncAlg), algid); 1.347 + if (rv != SECSuccess) 1.348 + return SECFailure; 1.349 + if (keysize >= 0) 1.350 + cinfo->keysize = keysize; 1.351 + return SECSuccess; 1.352 +} 1.353 + 1.354 +void 1.355 +NSS_CMSContentInfo_SetBulkKey(NSSCMSContentInfo *cinfo, PK11SymKey *bulkkey) 1.356 +{ 1.357 + cinfo->bulkkey = PK11_ReferenceSymKey(bulkkey); 1.358 + cinfo->keysize = PK11_GetKeyStrength(cinfo->bulkkey, &(cinfo->contentEncAlg)); 1.359 +} 1.360 + 1.361 +PK11SymKey * 1.362 +NSS_CMSContentInfo_GetBulkKey(NSSCMSContentInfo *cinfo) 1.363 +{ 1.364 + if (cinfo->bulkkey == NULL) 1.365 + return NULL; 1.366 + 1.367 + return PK11_ReferenceSymKey(cinfo->bulkkey); 1.368 +} 1.369 + 1.370 +int 1.371 +NSS_CMSContentInfo_GetBulkKeySize(NSSCMSContentInfo *cinfo) 1.372 +{ 1.373 + return cinfo->keysize; 1.374 +}