Coverage Report

Created: 2024-05-20 06:23

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