Coverage Report

Created: 2024-11-21 07:03

/src/nss-nspr/nss/lib/util/secdig.c
Line
Count
Source (jump to first uncovered line)
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
0
{
30
0
    return SEC_ASN1EncodeItem(poolp, dest, diginfo, sgn_DigestInfoTemplate);
31
0
}
32
33
SGNDigestInfo *
34
SGN_CreateDigestInfo(SECOidTag algorithm, const unsigned char *sig,
35
                     unsigned len)
36
6
{
37
6
    SGNDigestInfo *di;
38
6
    SECStatus rv;
39
6
    PLArenaPool *arena;
40
6
    SECItem *null_param;
41
6
    SECItem dummy_value;
42
43
    /* make sure we are encoding an actual hash function */
44
6
    if (HASH_GetHashTypeByOidTag(algorithm) == HASH_AlgNULL) {
45
0
        return NULL;
46
0
    }
47
6
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
48
6
    if (arena == NULL) {
49
0
        return NULL;
50
0
    }
51
52
6
    di = (SGNDigestInfo *)PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo));
53
6
    if (di == NULL) {
54
0
        PORT_FreeArena(arena, PR_FALSE);
55
0
        return NULL;
56
0
    }
57
58
6
    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
6
    dummy_value.data = NULL;
65
6
    dummy_value.len = 0;
66
6
    null_param = SEC_ASN1EncodeItem(NULL, NULL, &dummy_value, SEC_NullTemplate);
67
6
    if (null_param == NULL) {
68
0
        goto loser;
69
0
    }
70
71
6
    rv = SECOID_SetAlgorithmID(arena, &di->digestAlgorithm, algorithm,
72
6
                               null_param);
73
74
6
    SECITEM_FreeItem(null_param, PR_TRUE);
75
76
6
    if (rv != SECSuccess) {
77
0
        goto loser;
78
0
    }
79
80
6
    di->digest.data = (unsigned char *)PORT_ArenaAlloc(arena, len);
81
6
    if (di->digest.data == NULL) {
82
0
        goto loser;
83
0
    }
84
85
6
    di->digest.len = len;
86
6
    PORT_Memcpy(di->digest.data, sig, len);
87
6
    return di;
88
89
0
loser:
90
0
    SGN_DestroyDigestInfo(di);
91
0
    return NULL;
92
6
}
93
94
SGNDigestInfo *
95
SGN_DecodeDigestInfo(SECItem *didata)
96
0
{
97
0
    PLArenaPool *arena;
98
0
    SGNDigestInfo *di;
99
0
    SECStatus rv = SECFailure;
100
0
    SECItem diCopy = { siBuffer, NULL, 0 };
101
102
0
    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
103
0
    if (arena == NULL)
104
0
        return NULL;
105
106
0
    rv = SECITEM_CopyItem(arena, &diCopy, didata);
107
0
    if (rv != SECSuccess) {
108
0
        PORT_FreeArena(arena, PR_FALSE);
109
0
        return NULL;
110
0
    }
111
112
0
    di = (SGNDigestInfo *)PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo));
113
0
    if (di != NULL) {
114
0
        di->arena = arena;
115
0
        rv = SEC_QuickDERDecodeItem(arena, di, sgn_DigestInfoTemplate, &diCopy);
116
0
    }
117
118
0
    if ((di == NULL) || (rv != SECSuccess)) {
119
0
        PORT_FreeArena(arena, PR_FALSE);
120
0
        di = NULL;
121
0
    }
122
123
0
    return di;
124
0
}
125
126
void
127
SGN_DestroyDigestInfo(SGNDigestInfo *di)
128
6
{
129
6
    if (di && di->arena) {
130
6
        PORT_FreeArena(di->arena, PR_TRUE);
131
6
    }
132
133
6
    return;
134
6
}
135
136
SECStatus
137
SGN_CopyDigestInfo(PLArenaPool *poolp, SGNDigestInfo *a, SGNDigestInfo *b)
138
0
{
139
0
    SECStatus rv;
140
0
    void *mark;
141
142
0
    if ((poolp == NULL) || (a == NULL) || (b == NULL))
143
0
        return SECFailure;
144
145
0
    mark = PORT_ArenaMark(poolp);
146
0
    a->arena = poolp;
147
0
    rv = SECOID_CopyAlgorithmID(poolp, &a->digestAlgorithm,
148
0
                                &b->digestAlgorithm);
149
0
    if (rv == SECSuccess)
150
0
        rv = SECITEM_CopyItem(poolp, &a->digest, &b->digest);
151
152
0
    if (rv != SECSuccess) {
153
0
        PORT_ArenaRelease(poolp, mark);
154
0
    } else {
155
0
        PORT_ArenaUnmark(poolp, mark);
156
0
    }
157
158
0
    return rv;
159
0
}
160
161
SECComparison
162
SGN_CompareDigestInfo(SGNDigestInfo *a, SGNDigestInfo *b)
163
0
{
164
0
    SECComparison rv;
165
166
    /* Check signature algorithm's */
167
0
    rv = SECOID_CompareAlgorithmID(&a->digestAlgorithm, &b->digestAlgorithm);
168
0
    if (rv)
169
0
        return rv;
170
171
    /* Compare signature block length's */
172
0
    rv = SECITEM_CompareItem(&a->digest, &b->digest);
173
0
    return rv;
174
0
}