tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }