Coverage Report

Created: 2026-08-18 06:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/nss/lib/freebl/desblapi.c
Line
Count
Source
1
/*
2
 *  desblapi.c
3
 *
4
 *  core source file for DES-150 library
5
 *  Implement DES Modes of Operation and Triple-DES.
6
 *  Adapt DES-150 to blapi API.
7
 *
8
 * This Source Code Form is subject to the terms of the Mozilla Public
9
 * License, v. 2.0. If a copy of the MPL was not distributed with this
10
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
11
12
#ifdef FREEBL_NO_DEPEND
13
#include "stubs.h"
14
#endif
15
16
#include "des.h"
17
#include "blapii.h"
18
#include <stddef.h>
19
#include "secerr.h"
20
21
#if defined(NSS_X86_OR_X64)
22
/* Intel X86 CPUs do unaligned loads and stores without complaint. */
23
#define COPY8B(to, from, ptr) \
24
372k
    HALFPTR(to)               \
25
372k
    [0] = HALFPTR(from)[0];   \
26
372k
    HALFPTR(to)               \
27
372k
    [1] = HALFPTR(from)[1];
28
#else
29
#define COPY8B(to, from, ptr) memcpy(to, from, 8)
30
#endif
31
203k
#define COPY8BTOHALF(to, from) COPY8B(to, from, from)
32
169k
#define COPY8BFROMHALF(to, from) COPY8B(to, from, to)
33
34
static void
35
DES_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
36
118
{
37
494
    while (len) {
38
376
        DES_Do1Block(cx->ks0, in, out);
39
376
        len -= 8;
40
376
        in += 8;
41
376
        out += 8;
42
376
    }
43
118
}
44
45
static void
46
DES_EDE3_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
47
55.4k
{
48
388k
    while (len) {
49
332k
        DES_Do1Block(cx->ks0, in, out);
50
332k
        len -= 8;
51
332k
        in += 8;
52
332k
        DES_Do1Block(cx->ks1, out, out);
53
332k
        DES_Do1Block(cx->ks2, out, out);
54
332k
        out += 8;
55
332k
    }
56
55.4k
}
57
58
static void NO_SANITIZE_ALIGNMENT
59
DES_CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
60
162
{
61
162
    const BYTE *bufend = in + len;
62
162
    HALF vec[2];
63
64
1.81k
    while (in != bufend) {
65
1.65k
        COPY8BTOHALF(vec, in);
66
1.65k
        in += 8;
67
1.65k
        vec[0] ^= cx->iv[0];
68
1.65k
        vec[1] ^= cx->iv[1];
69
1.65k
        DES_Do1Block(cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
70
1.65k
        COPY8BFROMHALF(out, cx->iv);
71
1.65k
        out += 8;
72
1.65k
    }
73
162
}
74
75
static void NO_SANITIZE_ALIGNMENT
76
DES_CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
77
5.05k
{
78
5.05k
    const BYTE *bufend;
79
5.05k
    HALF oldciphertext[2];
80
5.05k
    HALF plaintext[2];
81
82
43.4k
    for (bufend = in + len; in != bufend;) {
83
38.3k
        oldciphertext[0] = cx->iv[0];
84
38.3k
        oldciphertext[1] = cx->iv[1];
85
38.3k
        COPY8BTOHALF(cx->iv, in);
86
38.3k
        in += 8;
87
38.3k
        DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
88
38.3k
        plaintext[0] ^= oldciphertext[0];
89
38.3k
        plaintext[1] ^= oldciphertext[1];
90
38.3k
        COPY8BFROMHALF(out, plaintext);
91
38.3k
        out += 8;
92
38.3k
    }
93
5.05k
}
94
95
static void NO_SANITIZE_ALIGNMENT
96
DES_EDE3CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
97
1.13k
{
98
1.13k
    const BYTE *bufend = in + len;
99
1.13k
    HALF vec[2];
100
101
4.98k
    while (in != bufend) {
102
3.84k
        COPY8BTOHALF(vec, in);
103
3.84k
        in += 8;
104
3.84k
        vec[0] ^= cx->iv[0];
105
3.84k
        vec[1] ^= cx->iv[1];
106
3.84k
        DES_Do1Block(cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
107
3.84k
        DES_Do1Block(cx->ks1, (BYTE *)cx->iv, (BYTE *)cx->iv);
108
3.84k
        DES_Do1Block(cx->ks2, (BYTE *)cx->iv, (BYTE *)cx->iv);
109
3.84k
        COPY8BFROMHALF(out, cx->iv);
110
3.84k
        out += 8;
111
3.84k
    }
112
1.13k
}
113
114
static void NO_SANITIZE_ALIGNMENT
115
DES_EDE3CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
116
23.5k
{
117
23.5k
    const BYTE *bufend;
118
23.5k
    HALF oldciphertext[2];
119
23.5k
    HALF plaintext[2];
120
121
148k
    for (bufend = in + len; in != bufend;) {
122
125k
        oldciphertext[0] = cx->iv[0];
123
125k
        oldciphertext[1] = cx->iv[1];
124
125k
        COPY8BTOHALF(cx->iv, in);
125
125k
        in += 8;
126
125k
        DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
127
125k
        DES_Do1Block(cx->ks1, (BYTE *)plaintext, (BYTE *)plaintext);
128
125k
        DES_Do1Block(cx->ks2, (BYTE *)plaintext, (BYTE *)plaintext);
129
125k
        plaintext[0] ^= oldciphertext[0];
130
125k
        plaintext[1] ^= oldciphertext[1];
131
125k
        COPY8BFROMHALF(out, plaintext);
132
125k
        out += 8;
133
125k
    }
134
23.5k
}
135
136
DESContext *
137
DES_AllocateContext(void)
138
0
{
139
0
    return PORT_ZNew(DESContext);
140
0
}
141
142
SECStatus
143
DES_InitContext(DESContext *cx, const unsigned char *key, unsigned int keylen,
144
                const unsigned char *iv, int mode, unsigned int encrypt,
145
                unsigned int unused)
146
90.2k
{
147
90.2k
    DESDirection opposite;
148
90.2k
    if (!cx) {
149
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
150
0
        return SECFailure;
151
0
    }
152
90.2k
    cx->direction = encrypt ? DES_ENCRYPT : DES_DECRYPT;
153
90.2k
    opposite = encrypt ? DES_DECRYPT : DES_ENCRYPT;
154
90.2k
    switch (mode) {
155
166
        case NSS_DES: /* DES ECB */
156
166
            DES_MakeSchedule(cx->ks0, key, cx->direction);
157
166
            cx->worker = &DES_ECB;
158
166
            break;
159
160
55.4k
        case NSS_DES_EDE3: /* DES EDE ECB */
161
55.4k
            cx->worker = &DES_EDE3_ECB;
162
55.4k
            if (encrypt) {
163
55.4k
                DES_MakeSchedule(cx->ks0, key, cx->direction);
164
55.4k
                DES_MakeSchedule(cx->ks1, key + 8, opposite);
165
55.4k
                DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
166
55.4k
            } else {
167
0
                DES_MakeSchedule(cx->ks2, key, cx->direction);
168
0
                DES_MakeSchedule(cx->ks1, key + 8, opposite);
169
0
                DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
170
0
            }
171
55.4k
            break;
172
173
11.8k
        case NSS_DES_CBC: /* DES CBC */
174
11.8k
            COPY8BTOHALF(cx->iv, iv);
175
11.8k
            cx->worker = encrypt ? &DES_CBCEn : &DES_CBCDe;
176
11.8k
            DES_MakeSchedule(cx->ks0, key, cx->direction);
177
11.8k
            break;
178
179
22.7k
        case NSS_DES_EDE3_CBC: /* DES EDE CBC */
180
22.7k
            COPY8BTOHALF(cx->iv, iv);
181
22.7k
            if (encrypt) {
182
11.3k
                cx->worker = &DES_EDE3CBCEn;
183
11.3k
                DES_MakeSchedule(cx->ks0, key, cx->direction);
184
11.3k
                DES_MakeSchedule(cx->ks1, key + 8, opposite);
185
11.3k
                DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
186
11.3k
            } else {
187
11.3k
                cx->worker = &DES_EDE3CBCDe;
188
11.3k
                DES_MakeSchedule(cx->ks2, key, cx->direction);
189
11.3k
                DES_MakeSchedule(cx->ks1, key + 8, opposite);
190
11.3k
                DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
191
11.3k
            }
192
22.7k
            break;
193
194
0
        default:
195
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
196
0
            return SECFailure;
197
90.2k
    }
198
90.2k
    return SECSuccess;
199
90.2k
}
200
201
DESContext *
202
DES_CreateContext(const BYTE *key, const BYTE *iv, int mode, PRBool encrypt)
203
90.2k
{
204
90.2k
    DESContext *cx = PORT_ZNew(DESContext);
205
90.2k
    SECStatus rv = DES_InitContext(cx, key, 0, iv, mode, encrypt, 0);
206
207
90.2k
    if (rv != SECSuccess) {
208
0
        PORT_ZFree(cx, sizeof *cx);
209
0
        cx = NULL;
210
0
    }
211
90.2k
    return cx;
212
90.2k
}
213
214
void
215
DES_DestroyContext(DESContext *cx, PRBool freeit)
216
90.2k
{
217
90.2k
    if (cx) {
218
90.2k
        memset(cx, 0, sizeof *cx);
219
90.2k
        if (freeit)
220
90.2k
            PORT_Free(cx);
221
90.2k
    }
222
90.2k
}
223
224
SECStatus
225
DES_Encrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
226
            unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
227
56.8k
{
228
229
56.8k
    if ((inLen % 8) != 0 || maxOutLen < inLen || !cx ||
230
56.8k
        cx->direction != DES_ENCRYPT) {
231
35
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
232
35
        return SECFailure;
233
35
    }
234
235
56.8k
    cx->worker(cx, out, in, inLen);
236
56.8k
    if (outLen)
237
56.8k
        *outLen = inLen;
238
56.8k
    return SECSuccess;
239
56.8k
}
240
241
SECStatus
242
DES_Decrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
243
            unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
244
28.7k
{
245
246
28.7k
    if ((inLen % 8) != 0 || maxOutLen < inLen || !cx ||
247
28.7k
        cx->direction != DES_DECRYPT) {
248
24
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
249
24
        return SECFailure;
250
24
    }
251
252
28.7k
    cx->worker(cx, out, in, inLen);
253
28.7k
    if (outLen)
254
28.7k
        *outLen = inLen;
255
28.7k
    return SECSuccess;
256
28.7k
}