tor-browser

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

secdig.c (4467B)


      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 #include "secdig.h"
      5 
      6 #include "secoid.h"
      7 #include "secasn1.h"
      8 #include "secerr.h"
      9 #include "hasht.h"
     10 #include "nsshash.h"
     11 
     12 /*
     13 * XXX Want to have a SGN_DecodeDigestInfo, like:
     14 *  SGNDigestInfo *SGN_DecodeDigestInfo(SECItem *didata);
     15 * that creates a pool and allocates from it and decodes didata into
     16 * the newly allocated DigestInfo structure.  Then fix secvfy.c (it
     17 * will no longer need an arena itself) to call this and then call
     18 * DestroyDigestInfo when it is done, then can remove the old template
     19 * above and keep our new template static and "hidden".
     20 */
     21 
     22 /*
     23 * XXX It might be nice to combine the following two functions (create
     24 * and encode).  I think that is all anybody ever wants to do anyway.
     25 */
     26 
     27 SECItem *
     28 SGN_EncodeDigestInfo(PLArenaPool *poolp, SECItem *dest, SGNDigestInfo *diginfo)
     29 {
     30    return SEC_ASN1EncodeItem(poolp, dest, diginfo, sgn_DigestInfoTemplate);
     31 }
     32 
     33 SGNDigestInfo *
     34 SGN_CreateDigestInfo(SECOidTag algorithm, const unsigned char *sig,
     35                     unsigned len)
     36 {
     37    SGNDigestInfo *di;
     38    SECStatus rv;
     39    PLArenaPool *arena;
     40    SECItem *null_param;
     41    SECItem dummy_value;
     42 
     43    /* make sure we are encoding an actual hash function */
     44    if (HASH_GetHashTypeByOidTag(algorithm) == HASH_AlgNULL) {
     45        return NULL;
     46    }
     47    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
     48    if (arena == NULL) {
     49        return NULL;
     50    }
     51 
     52    di = (SGNDigestInfo *)PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo));
     53    if (di == NULL) {
     54        PORT_FreeArena(arena, PR_FALSE);
     55        return NULL;
     56    }
     57 
     58    di->arena = arena;
     59 
     60    /*
     61     * PKCS #1 specifies that the AlgorithmID must have a NULL parameter
     62     * (as opposed to no parameter at all).
     63     */
     64    dummy_value.data = NULL;
     65    dummy_value.len = 0;
     66    null_param = SEC_ASN1EncodeItem(NULL, NULL, &dummy_value, SEC_NullTemplate);
     67    if (null_param == NULL) {
     68        goto loser;
     69    }
     70 
     71    rv = SECOID_SetAlgorithmID(arena, &di->digestAlgorithm, algorithm,
     72                               null_param);
     73 
     74    SECITEM_FreeItem(null_param, PR_TRUE);
     75 
     76    if (rv != SECSuccess) {
     77        goto loser;
     78    }
     79 
     80    di->digest.data = (unsigned char *)PORT_ArenaAlloc(arena, len);
     81    if (di->digest.data == NULL) {
     82        goto loser;
     83    }
     84 
     85    di->digest.len = len;
     86    PORT_Memcpy(di->digest.data, sig, len);
     87    return di;
     88 
     89 loser:
     90    SGN_DestroyDigestInfo(di);
     91    return NULL;
     92 }
     93 
     94 SGNDigestInfo *
     95 SGN_DecodeDigestInfo(SECItem *didata)
     96 {
     97    PLArenaPool *arena;
     98    SGNDigestInfo *di;
     99    SECStatus rv = SECFailure;
    100    SECItem diCopy = { siBuffer, NULL, 0 };
    101 
    102    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
    103    if (arena == NULL)
    104        return NULL;
    105 
    106    rv = SECITEM_CopyItem(arena, &diCopy, didata);
    107    if (rv != SECSuccess) {
    108        PORT_FreeArena(arena, PR_FALSE);
    109        return NULL;
    110    }
    111 
    112    di = (SGNDigestInfo *)PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo));
    113    if (di != NULL) {
    114        di->arena = arena;
    115        rv = SEC_QuickDERDecodeItem(arena, di, sgn_DigestInfoTemplate, &diCopy);
    116    }
    117 
    118    if ((di == NULL) || (rv != SECSuccess)) {
    119        PORT_FreeArena(arena, PR_FALSE);
    120        di = NULL;
    121    }
    122 
    123    return di;
    124 }
    125 
    126 void
    127 SGN_DestroyDigestInfo(SGNDigestInfo *di)
    128 {
    129    if (di && di->arena) {
    130        PORT_FreeArena(di->arena, PR_TRUE);
    131    }
    132 
    133    return;
    134 }
    135 
    136 SECStatus
    137 SGN_CopyDigestInfo(PLArenaPool *poolp, SGNDigestInfo *a, SGNDigestInfo *b)
    138 {
    139    SECStatus rv;
    140    void *mark;
    141 
    142    if ((poolp == NULL) || (a == NULL) || (b == NULL))
    143        return SECFailure;
    144 
    145    mark = PORT_ArenaMark(poolp);
    146    a->arena = poolp;
    147    rv = SECOID_CopyAlgorithmID(poolp, &a->digestAlgorithm,
    148                                &b->digestAlgorithm);
    149    if (rv == SECSuccess)
    150        rv = SECITEM_CopyItem(poolp, &a->digest, &b->digest);
    151 
    152    if (rv != SECSuccess) {
    153        PORT_ArenaRelease(poolp, mark);
    154    } else {
    155        PORT_ArenaUnmark(poolp, mark);
    156    }
    157 
    158    return rv;
    159 }
    160 
    161 SECComparison
    162 SGN_CompareDigestInfo(SGNDigestInfo *a, SGNDigestInfo *b)
    163 {
    164    SECComparison rv;
    165 
    166    /* Check signature algorithm's */
    167    rv = SECOID_CompareAlgorithmID(&a->digestAlgorithm, &b->digestAlgorithm);
    168    if (rv)
    169        return rv;
    170 
    171    /* Compare signature block length's */
    172    rv = SECITEM_CompareItem(&a->digest, &b->digest);
    173    return rv;
    174 }