Coverage Report

Created: 2024-11-21 07:03

/src/nss-nspr/nss/lib/freebl/desblapi.c
Line
Count
Source (jump to first uncovered line)
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
1
    HALFPTR(to)               \
25
1
    [0] = HALFPTR(from)[0];   \
26
1
    HALFPTR(to)               \
27
1
    [1] = HALFPTR(from)[1];
28
#else
29
#define COPY8B(to, from, ptr) memcpy(to, from, 8)
30
#endif
31
1
#define COPY8BTOHALF(to, from) COPY8B(to, from, from)
32
0
#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
1
{
37
2
    while (len) {
38
1
        DES_Do1Block(cx->ks0, in, out);
39
1
        len -= 8;
40
1
        in += 8;
41
1
        out += 8;
42
1
    }
43
1
}
44
45
static void
46
DES_EDE3_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
47
0
{
48
0
    while (len) {
49
0
        DES_Do1Block(cx->ks0, in, out);
50
0
        len -= 8;
51
0
        in += 8;
52
0
        DES_Do1Block(cx->ks1, out, out);
53
0
        DES_Do1Block(cx->ks2, out, out);
54
0
        out += 8;
55
0
    }
56
0
}
57
58
static void NO_SANITIZE_ALIGNMENT
59
DES_CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
60
0
{
61
0
    const BYTE *bufend = in + len;
62
0
    HALF vec[2];
63
64
0
    while (in != bufend) {
65
0
        COPY8BTOHALF(vec, in);
66
0
        in += 8;
67
0
        vec[0] ^= cx->iv[0];
68
0
        vec[1] ^= cx->iv[1];
69
0
        DES_Do1Block(cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
70
0
        COPY8BFROMHALF(out, cx->iv);
71
0
        out += 8;
72
0
    }
73
0
}
74
75
static void NO_SANITIZE_ALIGNMENT
76
DES_CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
77
0
{
78
0
    const BYTE *bufend;
79
0
    HALF oldciphertext[2];
80
0
    HALF plaintext[2];
81
82
0
    for (bufend = in + len; in != bufend;) {
83
0
        oldciphertext[0] = cx->iv[0];
84
0
        oldciphertext[1] = cx->iv[1];
85
0
        COPY8BTOHALF(cx->iv, in);
86
0
        in += 8;
87
0
        DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
88
0
        plaintext[0] ^= oldciphertext[0];
89
0
        plaintext[1] ^= oldciphertext[1];
90
0
        COPY8BFROMHALF(out, plaintext);
91
0
        out += 8;
92
0
    }
93
0
}
94
95
static void NO_SANITIZE_ALIGNMENT
96
DES_EDE3CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
97
0
{
98
0
    const BYTE *bufend = in + len;
99
0
    HALF vec[2];
100
101
0
    while (in != bufend) {
102
0
        COPY8BTOHALF(vec, in);
103
0
        in += 8;
104
0
        vec[0] ^= cx->iv[0];
105
0
        vec[1] ^= cx->iv[1];
106
0
        DES_Do1Block(cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
107
0
        DES_Do1Block(cx->ks1, (BYTE *)cx->iv, (BYTE *)cx->iv);
108
0
        DES_Do1Block(cx->ks2, (BYTE *)cx->iv, (BYTE *)cx->iv);
109
0
        COPY8BFROMHALF(out, cx->iv);
110
0
        out += 8;
111
0
    }
112
0
}
113
114
static void NO_SANITIZE_ALIGNMENT
115
DES_EDE3CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
116
0
{
117
0
    const BYTE *bufend;
118
0
    HALF oldciphertext[2];
119
0
    HALF plaintext[2];
120
121
0
    for (bufend = in + len; in != bufend;) {
122
0
        oldciphertext[0] = cx->iv[0];
123
0
        oldciphertext[1] = cx->iv[1];
124
0
        COPY8BTOHALF(cx->iv, in);
125
0
        in += 8;
126
0
        DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
127
0
        DES_Do1Block(cx->ks1, (BYTE *)plaintext, (BYTE *)plaintext);
128
0
        DES_Do1Block(cx->ks2, (BYTE *)plaintext, (BYTE *)plaintext);
129
0
        plaintext[0] ^= oldciphertext[0];
130
0
        plaintext[1] ^= oldciphertext[1];
131
0
        COPY8BFROMHALF(out, plaintext);
132
0
        out += 8;
133
0
    }
134
0
}
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
3
{
147
3
    DESDirection opposite;
148
3
    if (!cx) {
149
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
150
0
        return SECFailure;
151
0
    }
152
3
    cx->direction = encrypt ? DES_ENCRYPT : DES_DECRYPT;
153
3
    opposite = encrypt ? DES_DECRYPT : DES_ENCRYPT;
154
3
    switch (mode) {
155
2
        case NSS_DES: /* DES ECB */
156
2
            DES_MakeSchedule(cx->ks0, key, cx->direction);
157
2
            cx->worker = &DES_ECB;
158
2
            break;
159
160
0
        case NSS_DES_EDE3: /* DES EDE ECB */
161
0
            cx->worker = &DES_EDE3_ECB;
162
0
            if (encrypt) {
163
0
                DES_MakeSchedule(cx->ks0, key, cx->direction);
164
0
                DES_MakeSchedule(cx->ks1, key + 8, opposite);
165
0
                DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
166
0
            } 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
0
            break;
172
173
1
        case NSS_DES_CBC: /* DES CBC */
174
1
            COPY8BTOHALF(cx->iv, iv);
175
1
            cx->worker = encrypt ? &DES_CBCEn : &DES_CBCDe;
176
1
            DES_MakeSchedule(cx->ks0, key, cx->direction);
177
1
            break;
178
179
0
        case NSS_DES_EDE3_CBC: /* DES EDE CBC */
180
0
            COPY8BTOHALF(cx->iv, iv);
181
0
            if (encrypt) {
182
0
                cx->worker = &DES_EDE3CBCEn;
183
0
                DES_MakeSchedule(cx->ks0, key, cx->direction);
184
0
                DES_MakeSchedule(cx->ks1, key + 8, opposite);
185
0
                DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
186
0
            } else {
187
0
                cx->worker = &DES_EDE3CBCDe;
188
0
                DES_MakeSchedule(cx->ks2, key, cx->direction);
189
0
                DES_MakeSchedule(cx->ks1, key + 8, opposite);
190
0
                DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
191
0
            }
192
0
            break;
193
194
0
        default:
195
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
196
0
            return SECFailure;
197
3
    }
198
3
    return SECSuccess;
199
3
}
200
201
DESContext *
202
DES_CreateContext(const BYTE *key, const BYTE *iv, int mode, PRBool encrypt)
203
3
{
204
3
    DESContext *cx = PORT_ZNew(DESContext);
205
3
    SECStatus rv = DES_InitContext(cx, key, 0, iv, mode, encrypt, 0);
206
207
3
    if (rv != SECSuccess) {
208
0
        PORT_ZFree(cx, sizeof *cx);
209
0
        cx = NULL;
210
0
    }
211
3
    return cx;
212
3
}
213
214
void
215
DES_DestroyContext(DESContext *cx, PRBool freeit)
216
3
{
217
3
    if (cx) {
218
3
        memset(cx, 0, sizeof *cx);
219
3
        if (freeit)
220
3
            PORT_Free(cx);
221
3
    }
222
3
}
223
224
SECStatus
225
DES_Encrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
226
            unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
227
1
{
228
229
1
    if ((inLen % 8) != 0 || maxOutLen < inLen || !cx ||
230
1
        cx->direction != DES_ENCRYPT) {
231
1
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
232
1
        return SECFailure;
233
1
    }
234
235
0
    cx->worker(cx, out, in, inLen);
236
0
    if (outLen)
237
0
        *outLen = inLen;
238
0
    return SECSuccess;
239
1
}
240
241
SECStatus
242
DES_Decrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
243
            unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
244
3
{
245
246
3
    if ((inLen % 8) != 0 || maxOutLen < inLen || !cx ||
247
3
        cx->direction != DES_DECRYPT) {
248
2
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
249
2
        return SECFailure;
250
2
    }
251
252
1
    cx->worker(cx, out, in, inLen);
253
1
    if (outLen)
254
1
        *outLen = inLen;
255
1
    return SECSuccess;
256
3
}