Coverage Report

Created: 2025-07-04 06:19

/src/nss/lib/pkcs7/p7local.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
5
/*
6
 * Support routines for PKCS7 implementation, none of which are exported.
7
 * This file should only contain things that are needed by both the
8
 * encoding/creation side *and* the decoding/decryption side.  Anything
9
 * else should be static routines in the appropriate file.
10
 */
11
12
#include "p7local.h"
13
14
#include "cryptohi.h"
15
#include "secasn1.h"
16
#include "secoid.h"
17
#include "secitem.h"
18
#include "pk11func.h"
19
#include "secpkcs5.h"
20
#include "secerr.h"
21
22
#include <limits.h>
23
24
/*
25
 * -------------------------------------------------------------------
26
 * Cipher stuff.
27
 */
28
29
typedef SECStatus (*sec_pkcs7_cipher_function)(void *,
30
                                               unsigned char *,
31
                                               unsigned *,
32
                                               unsigned int,
33
                                               const unsigned char *,
34
                                               unsigned int);
35
typedef SECStatus (*sec_pkcs7_cipher_destroy)(void *, PRBool);
36
37
static SECStatus
38
SECPKCS7Cipher_PK11_CipherOp(void *vctx, unsigned char *output,
39
                             unsigned int *outputLen, unsigned int maxOutputLen,
40
                             const unsigned char *input, unsigned int inputLen)
41
3.96k
{
42
3.96k
    PK11Context *ctx = vctx;
43
3.96k
    PORT_Assert(maxOutputLen <= INT_MAX);
44
3.96k
    int signedOutputLen = maxOutputLen;
45
3.96k
    SECStatus rv = PK11_CipherOp(ctx, output, &signedOutputLen, maxOutputLen, input, inputLen);
46
3.96k
    PORT_Assert(signedOutputLen >= 0);
47
3.96k
    *outputLen = signedOutputLen;
48
3.96k
    return rv;
49
3.96k
}
50
static SECStatus
51
SECPKCS7Cipher_PK11_DestroyContext(void *vctx, PRBool freeit)
52
4.49k
{
53
4.49k
    PK11Context *ctx = vctx;
54
4.49k
    PK11_DestroyContext(ctx, freeit);
55
4.49k
    return SECSuccess;
56
4.49k
}
57
58
0
#define BLOCK_SIZE 4096
59
60
struct sec_pkcs7_cipher_object {
61
    void *cx;
62
    sec_pkcs7_cipher_function doit;
63
    sec_pkcs7_cipher_destroy destroy;
64
    PRBool encrypt;
65
    int block_size;
66
    int pad_size;
67
    int pending_count;
68
    unsigned char pending_buf[BLOCK_SIZE];
69
};
70
71
SEC_ASN1_MKSUB(CERT_IssuerAndSNTemplate)
72
SEC_ASN1_MKSUB(CERT_SetOfSignedCrlTemplate)
73
SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
74
SEC_ASN1_MKSUB(SEC_OctetStringTemplate)
75
SEC_ASN1_MKSUB(SEC_SetOfAnyTemplate)
76
77
/*
78
 * Create a cipher object to do decryption,  based on the given bulk
79
 * encryption key and algorithm identifier (which may include an iv).
80
 *
81
 * XXX This interface, or one similar, would be really nice available
82
 * in general...  I tried to keep the pkcs7-specific stuff (mostly
83
 * having to do with padding) out of here.
84
 *
85
 * XXX Once both are working, it might be nice to combine this and the
86
 * function below (for starting up encryption) into one routine, and just
87
 * have two simple cover functions which call it.
88
 */
89
sec_PKCS7CipherObject *
90
sec_PKCS7CreateDecryptObject(PK11SymKey *key, SECAlgorithmID *algid)
91
4.49k
{
92
4.49k
    sec_PKCS7CipherObject *result;
93
4.49k
    SECOidTag algtag;
94
4.49k
    void *ciphercx;
95
4.49k
    CK_MECHANISM_TYPE cryptoMechType;
96
4.49k
    PK11SlotInfo *slot;
97
4.49k
    SECItem *param = NULL;
98
99
4.49k
    result = (struct sec_pkcs7_cipher_object *)
100
4.49k
        PORT_ZAlloc(sizeof(struct sec_pkcs7_cipher_object));
101
4.49k
    if (result == NULL)
102
0
        return NULL;
103
104
4.49k
    ciphercx = NULL;
105
4.49k
    algtag = SECOID_GetAlgorithmTag(algid);
106
107
4.49k
    if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
108
4.49k
        SECItem *pwitem;
109
110
4.49k
        pwitem = (SECItem *)PK11_GetSymKeyUserData(key);
111
4.49k
        if (!pwitem) {
112
0
            PORT_Free(result);
113
0
            return NULL;
114
0
        }
115
116
4.49k
        cryptoMechType = PK11_GetPBECryptoMechanism(algid, &param, pwitem);
117
4.49k
        if (cryptoMechType == CKM_INVALID_MECHANISM) {
118
0
            PORT_Free(result);
119
0
            SECITEM_FreeItem(param, PR_TRUE);
120
0
            return NULL;
121
0
        }
122
4.49k
    } else {
123
0
        cryptoMechType = PK11_AlgtagToMechanism(algtag);
124
0
        param = PK11_ParamFromAlgid(algid);
125
0
        if (param == NULL) {
126
0
            PORT_Free(result);
127
0
            return NULL;
128
0
        }
129
0
    }
130
131
4.49k
    result->pad_size = PK11_GetBlockSize(cryptoMechType, param);
132
4.49k
    slot = PK11_GetSlotFromKey(key);
133
4.49k
    result->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : result->pad_size;
134
4.49k
    PK11_FreeSlot(slot);
135
4.49k
    ciphercx = PK11_CreateContextBySymKey(cryptoMechType, CKA_DECRYPT,
136
4.49k
                                          key, param);
137
4.49k
    SECITEM_FreeItem(param, PR_TRUE);
138
4.49k
    if (ciphercx == NULL) {
139
0
        PORT_Free(result);
140
0
        return NULL;
141
0
    }
142
143
4.49k
    result->cx = ciphercx;
144
4.49k
    result->doit = SECPKCS7Cipher_PK11_CipherOp;
145
4.49k
    result->destroy = SECPKCS7Cipher_PK11_DestroyContext;
146
4.49k
    result->encrypt = PR_FALSE;
147
4.49k
    result->pending_count = 0;
148
149
4.49k
    return result;
150
4.49k
}
151
152
/*
153
 * Create a cipher object to do encryption, based on the given bulk
154
 * encryption key and algorithm tag.  Fill in the algorithm identifier
155
 * (which may include an iv) appropriately.
156
 *
157
 * XXX This interface, or one similar, would be really nice available
158
 * in general...  I tried to keep the pkcs7-specific stuff (mostly
159
 * having to do with padding) out of here.
160
 *
161
 * XXX Once both are working, it might be nice to combine this and the
162
 * function above (for starting up decryption) into one routine, and just
163
 * have two simple cover functions which call it.
164
 */
165
sec_PKCS7CipherObject *
166
sec_PKCS7CreateEncryptObject(PLArenaPool *poolp, PK11SymKey *key,
167
                             SECOidTag algtag, SECAlgorithmID *algid)
168
0
{
169
0
    sec_PKCS7CipherObject *result;
170
0
    void *ciphercx;
171
0
    SECStatus rv;
172
0
    CK_MECHANISM_TYPE cryptoMechType;
173
0
    PK11SlotInfo *slot;
174
0
    SECItem *param = NULL;
175
0
    PRBool needToEncodeAlgid = PR_FALSE;
176
177
0
    result = (struct sec_pkcs7_cipher_object *)
178
0
        PORT_ZAlloc(sizeof(struct sec_pkcs7_cipher_object));
179
0
    if (result == NULL)
180
0
        return NULL;
181
182
0
    ciphercx = NULL;
183
0
    if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
184
0
        SECItem *pwitem;
185
186
0
        pwitem = (SECItem *)PK11_GetSymKeyUserData(key);
187
0
        if (!pwitem) {
188
0
            PORT_Free(result);
189
0
            return NULL;
190
0
        }
191
192
0
        cryptoMechType = PK11_GetPBECryptoMechanism(algid, &param, pwitem);
193
0
        if (cryptoMechType == CKM_INVALID_MECHANISM) {
194
0
            PORT_Free(result);
195
0
            SECITEM_FreeItem(param, PR_TRUE);
196
0
            return NULL;
197
0
        }
198
0
    } else {
199
0
        cryptoMechType = PK11_AlgtagToMechanism(algtag);
200
0
        param = PK11_GenerateNewParam(cryptoMechType, key);
201
0
        if (param == NULL) {
202
0
            PORT_Free(result);
203
0
            return NULL;
204
0
        }
205
0
        needToEncodeAlgid = PR_TRUE;
206
0
    }
207
208
0
    result->pad_size = PK11_GetBlockSize(cryptoMechType, param);
209
0
    slot = PK11_GetSlotFromKey(key);
210
0
    result->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : result->pad_size;
211
0
    PK11_FreeSlot(slot);
212
0
    ciphercx = PK11_CreateContextBySymKey(cryptoMechType, CKA_ENCRYPT,
213
0
                                          key, param);
214
0
    if (ciphercx == NULL) {
215
0
        PORT_Free(result);
216
0
        SECITEM_FreeItem(param, PR_TRUE);
217
0
        return NULL;
218
0
    }
219
220
    /*
221
     * These are placed after the CreateContextBySymKey() because some
222
     * mechanisms have to generate their IVs from their card (i.e. FORTEZZA).
223
     * Don't move it from here.
224
     */
225
0
    if (needToEncodeAlgid) {
226
0
        rv = PK11_ParamToAlgid(algtag, param, poolp, algid);
227
0
        if (rv != SECSuccess) {
228
0
            PORT_Free(result);
229
0
            SECITEM_FreeItem(param, PR_TRUE);
230
0
            PK11_DestroyContext(ciphercx, PR_TRUE);
231
0
            return NULL;
232
0
        }
233
0
    }
234
0
    SECITEM_FreeItem(param, PR_TRUE);
235
236
0
    result->cx = ciphercx;
237
0
    result->doit = SECPKCS7Cipher_PK11_CipherOp;
238
0
    result->destroy = SECPKCS7Cipher_PK11_DestroyContext;
239
0
    result->encrypt = PR_TRUE;
240
0
    result->pending_count = 0;
241
242
0
    return result;
243
0
}
244
245
/*
246
 * Destroy the cipher object.
247
 */
248
static void
249
sec_pkcs7_destroy_cipher(sec_PKCS7CipherObject *obj)
250
4.49k
{
251
4.49k
    (*obj->destroy)(obj->cx, PR_TRUE);
252
4.49k
    PORT_Free(obj);
253
4.49k
}
254
255
void
256
sec_PKCS7DestroyDecryptObject(sec_PKCS7CipherObject *obj)
257
4.49k
{
258
4.49k
    PORT_Assert(obj != NULL);
259
4.49k
    if (obj == NULL)
260
0
        return;
261
4.49k
    PORT_Assert(!obj->encrypt);
262
4.49k
    sec_pkcs7_destroy_cipher(obj);
263
4.49k
}
264
265
void
266
sec_PKCS7DestroyEncryptObject(sec_PKCS7CipherObject *obj)
267
0
{
268
0
    PORT_Assert(obj != NULL);
269
0
    if (obj == NULL)
270
0
        return;
271
0
    PORT_Assert(obj->encrypt);
272
0
    sec_pkcs7_destroy_cipher(obj);
273
0
}
274
275
/*
276
 * XXX I think all of the following lengths should be longs instead
277
 * of ints, but our current crypto interface uses ints, so I did too.
278
 */
279
280
/*
281
 * What will be the output length of the next call to decrypt?
282
 * Result can be used to perform memory allocations.  Note that the amount
283
 * is exactly accurate only when not doing a block cipher or when final
284
 * is false, otherwise it is an upper bound on the amount because until
285
 * we see the data we do not know how many padding bytes there are
286
 * (always between 1 and bsize).
287
 *
288
 * Note that this can return zero, which does not mean that the decrypt
289
 * operation can be skipped!  (It simply means that there are not enough
290
 * bytes to make up an entire block; the bytes will be reserved until
291
 * there are enough to encrypt/decrypt at least one block.)  However,
292
 * if zero is returned it *does* mean that no output buffer need be
293
 * passed in to the subsequent decrypt operation, as no output bytes
294
 * will be stored.
295
 */
296
unsigned int
297
sec_PKCS7DecryptLength(sec_PKCS7CipherObject *obj, unsigned int input_len,
298
                       PRBool final)
299
26.2k
{
300
26.2k
    int blocks, block_size;
301
302
26.2k
    PORT_Assert(!obj->encrypt);
303
304
26.2k
    block_size = obj->block_size;
305
306
    /*
307
     * If this is not a block cipher, then we always have the same
308
     * number of output bytes as we had input bytes.
309
     */
310
26.2k
    if (block_size == 0)
311
0
        return input_len;
312
313
    /*
314
     * On the final call, we will always use up all of the pending
315
     * bytes plus all of the input bytes, *but*, there will be padding
316
     * at the end and we cannot predict how many bytes of padding we
317
     * will end up removing.  The amount given here is actually known
318
     * to be at least 1 byte too long (because we know we will have
319
     * at least 1 byte of padding), but seemed clearer/better to me.
320
     */
321
26.2k
    if (final)
322
4.45k
        return obj->pending_count + input_len;
323
324
    /*
325
     * Okay, this amount is exactly what we will output on the
326
     * next cipher operation.  We will always hang onto the last
327
     * 1 - block_size bytes for non-final operations.  That is,
328
     * we will do as many complete blocks as we can *except* the
329
     * last block (complete or partial).  (This is because until
330
     * we know we are at the end, we cannot know when to interpret
331
     * and removing the padding byte(s), which are guaranteed to
332
     * be there.)
333
     */
334
21.7k
    blocks = (obj->pending_count + input_len - 1) / block_size;
335
21.7k
    return blocks * block_size;
336
26.2k
}
337
338
/*
339
 * What will be the output length of the next call to encrypt?
340
 * Result can be used to perform memory allocations.
341
 *
342
 * Note that this can return zero, which does not mean that the encrypt
343
 * operation can be skipped!  (It simply means that there are not enough
344
 * bytes to make up an entire block; the bytes will be reserved until
345
 * there are enough to encrypt/decrypt at least one block.)  However,
346
 * if zero is returned it *does* mean that no output buffer need be
347
 * passed in to the subsequent encrypt operation, as no output bytes
348
 * will be stored.
349
 */
350
unsigned int
351
sec_PKCS7EncryptLength(sec_PKCS7CipherObject *obj, unsigned int input_len,
352
                       PRBool final)
353
0
{
354
0
    int blocks, block_size;
355
0
    int pad_size;
356
357
0
    PORT_Assert(obj->encrypt);
358
359
0
    block_size = obj->block_size;
360
0
    pad_size = obj->pad_size;
361
362
    /*
363
     * If this is not a block cipher, then we always have the same
364
     * number of output bytes as we had input bytes.
365
     */
366
0
    if (block_size == 0)
367
0
        return input_len;
368
369
    /*
370
     * On the final call, we only send out what we need for
371
     * remaining bytes plus the padding.  (There is always padding,
372
     * so even if we have an exact number of blocks as input, we
373
     * will add another full block that is just padding.)
374
     */
375
0
    if (final) {
376
0
        if (pad_size == 0) {
377
0
            return obj->pending_count + input_len;
378
0
        } else {
379
0
            blocks = (obj->pending_count + input_len) / pad_size;
380
0
            blocks++;
381
0
            return blocks * pad_size;
382
0
        }
383
0
    }
384
385
    /*
386
     * Now, count the number of complete blocks of data we have.
387
     */
388
0
    blocks = (obj->pending_count + input_len) / block_size;
389
390
0
    return blocks * block_size;
391
0
}
392
393
/*
394
 * Decrypt a given length of input buffer (starting at "input" and
395
 * containing "input_len" bytes), placing the decrypted bytes in
396
 * "output" and storing the output length in "*output_len_p".
397
 * "obj" is the return value from sec_PKCS7CreateDecryptObject.
398
 * When "final" is true, this is the last of the data to be decrypted.
399
 *
400
 * This is much more complicated than it sounds when the cipher is
401
 * a block-type, meaning that the decryption function will only
402
 * operate on whole blocks.  But our caller is operating stream-wise,
403
 * and can pass in any number of bytes.  So we need to keep track
404
 * of block boundaries.  We save excess bytes between calls in "obj".
405
 * We also need to determine which bytes are padding, and remove
406
 * them from the output.  We can only do this step when we know we
407
 * have the final block of data.  PKCS #7 specifies that the padding
408
 * used for a block cipher is a string of bytes, each of whose value is
409
 * the same as the length of the padding, and that all data is padded.
410
 * (Even data that starts out with an exact multiple of blocks gets
411
 * added to it another block, all of which is padding.)
412
 */
413
SECStatus
414
sec_PKCS7Decrypt(sec_PKCS7CipherObject *obj, unsigned char *output,
415
                 unsigned int *output_len_p, unsigned int max_output_len,
416
                 const unsigned char *input, unsigned int input_len,
417
                 PRBool final)
418
10.8k
{
419
10.8k
    unsigned int blocks, bsize, pcount, padsize;
420
10.8k
    unsigned int max_needed, ifraglen, ofraglen, output_len;
421
10.8k
    unsigned char *pbuf;
422
10.8k
    SECStatus rv;
423
424
10.8k
    PORT_Assert(!obj->encrypt);
425
426
    /*
427
     * Check that we have enough room for the output.  Our caller should
428
     * already handle this; failure is really an internal error (i.e. bug).
429
     */
430
10.8k
    max_needed = sec_PKCS7DecryptLength(obj, input_len, final);
431
10.8k
    PORT_Assert(max_output_len >= max_needed);
432
10.8k
    if (max_output_len < max_needed) {
433
        /* PORT_SetError (XXX); */
434
0
        return SECFailure;
435
0
    }
436
437
    /*
438
     * hardware encryption does not like small decryption sizes here, so we
439
     * allow both blocking and padding.
440
     */
441
10.8k
    bsize = obj->block_size;
442
10.8k
    padsize = obj->pad_size;
443
444
    /*
445
     * When no blocking or padding work to do, we can simply call the
446
     * cipher function and we are done.
447
     */
448
10.8k
    if (bsize == 0) {
449
0
        return (*obj->doit)(obj->cx, output, output_len_p, max_output_len,
450
0
                            input, input_len);
451
0
    }
452
453
10.8k
    pcount = obj->pending_count;
454
10.8k
    pbuf = obj->pending_buf;
455
456
10.8k
    output_len = 0;
457
458
10.8k
    if (pcount) {
459
        /*
460
         * Try to fill in an entire block, starting with the bytes
461
         * we already have saved away.
462
         */
463
50.3k
        while (input_len && pcount < bsize) {
464
39.5k
            pbuf[pcount++] = *input++;
465
39.5k
            input_len--;
466
39.5k
        }
467
        /*
468
         * If we have at most a whole block and this is not our last call,
469
         * then we are done for now.  (We do not try to decrypt a lone
470
         * single block because we cannot interpret the padding bytes
471
         * until we know we are handling the very last block of all input.)
472
         */
473
10.8k
        if (input_len == 0 && !final) {
474
7.61k
            obj->pending_count = pcount;
475
7.61k
            if (output_len_p)
476
0
                *output_len_p = 0;
477
7.61k
            return SECSuccess;
478
7.61k
        }
479
        /*
480
         * Given the logic above, we expect to have a full block by now.
481
         * If we do not, there is something wrong, either with our own
482
         * logic or with (length of) the data given to us.
483
         */
484
3.21k
        if ((padsize != 0) && (pcount % padsize) != 0) {
485
0
            PORT_Assert(final);
486
0
            PORT_SetError(SEC_ERROR_BAD_DATA);
487
0
            return SECFailure;
488
0
        }
489
        /*
490
         * Decrypt the block.
491
         */
492
3.21k
        rv = (*obj->doit)(obj->cx, output, &ofraglen, max_output_len,
493
3.21k
                          pbuf, pcount);
494
3.21k
        if (rv != SECSuccess)
495
0
            return rv;
496
497
        /*
498
         * For now anyway, all of our ciphers have the same number of
499
         * bytes of output as they do input.  If this ever becomes untrue,
500
         * then sec_PKCS7DecryptLength needs to be made smarter!
501
         */
502
3.21k
        PORT_Assert(ofraglen == pcount);
503
504
        /*
505
         * Account for the bytes now in output.
506
         */
507
3.21k
        max_output_len -= ofraglen;
508
3.21k
        output_len += ofraglen;
509
3.21k
        output += ofraglen;
510
3.21k
    }
511
512
    /*
513
     * If this is our last call, we expect to have an exact number of
514
     * blocks left to be decrypted; we will decrypt them all.
515
     *
516
     * If not our last call, we always save between 1 and bsize bytes
517
     * until next time.  (We must do this because we cannot be sure
518
     * that none of the decrypted bytes are padding bytes until we
519
     * have at least another whole block of data.  You cannot tell by
520
     * looking -- the data could be anything -- you can only tell by
521
     * context, knowing you are looking at the last block.)  We could
522
     * decrypt a whole block now but it is easier if we just treat it
523
     * the same way we treat partial block bytes.
524
     */
525
3.26k
    if (final) {
526
1
        if (padsize) {
527
1
            blocks = input_len / padsize;
528
1
            ifraglen = blocks * padsize;
529
1
        } else
530
0
            ifraglen = input_len;
531
1
        PORT_Assert(ifraglen == input_len);
532
533
1
        if (ifraglen != input_len) {
534
0
            PORT_SetError(SEC_ERROR_BAD_DATA);
535
0
            return SECFailure;
536
0
        }
537
3.26k
    } else {
538
3.26k
        blocks = (input_len - 1) / bsize;
539
3.26k
        ifraglen = blocks * bsize;
540
3.26k
        PORT_Assert(ifraglen < input_len);
541
542
3.26k
        pcount = input_len - ifraglen;
543
3.26k
        PORT_Memcpy(pbuf, input + ifraglen, pcount);
544
3.26k
        obj->pending_count = pcount;
545
3.26k
    }
546
547
3.26k
    if (ifraglen) {
548
751
        rv = (*obj->doit)(obj->cx, output, &ofraglen, max_output_len,
549
751
                          input, ifraglen);
550
751
        if (rv != SECSuccess)
551
0
            return rv;
552
553
        /*
554
         * For now anyway, all of our ciphers have the same number of
555
         * bytes of output as they do input.  If this ever becomes untrue,
556
         * then sec_PKCS7DecryptLength needs to be made smarter!
557
         */
558
751
        PORT_Assert(ifraglen == ofraglen);
559
751
        if (ifraglen != ofraglen) {
560
0
            PORT_SetError(SEC_ERROR_BAD_DATA);
561
0
            return SECFailure;
562
0
        }
563
564
751
        output_len += ofraglen;
565
2.51k
    } else {
566
2.51k
        ofraglen = 0;
567
2.51k
    }
568
569
    /*
570
     * If we just did our very last block, "remove" the padding by
571
     * adjusting the output length.
572
     */
573
3.26k
    if (final && (padsize != 0)) {
574
1
        unsigned int padlen = *(output + ofraglen - 1);
575
1
        if (padlen == 0 || padlen > padsize) {
576
1
            PORT_SetError(SEC_ERROR_BAD_DATA);
577
1
            return SECFailure;
578
1
        }
579
0
        output_len -= padlen;
580
0
    }
581
582
3.26k
    PORT_Assert(output_len_p != NULL || output_len == 0);
583
3.26k
    if (output_len_p != NULL)
584
3.22k
        *output_len_p = output_len;
585
586
3.26k
    return SECSuccess;
587
3.26k
}
588
589
/*
590
 * Encrypt a given length of input buffer (starting at "input" and
591
 * containing "input_len" bytes), placing the encrypted bytes in
592
 * "output" and storing the output length in "*output_len_p".
593
 * "obj" is the return value from sec_PKCS7CreateEncryptObject.
594
 * When "final" is true, this is the last of the data to be encrypted.
595
 *
596
 * This is much more complicated than it sounds when the cipher is
597
 * a block-type, meaning that the encryption function will only
598
 * operate on whole blocks.  But our caller is operating stream-wise,
599
 * and can pass in any number of bytes.  So we need to keep track
600
 * of block boundaries.  We save excess bytes between calls in "obj".
601
 * We also need to add padding bytes at the end.  PKCS #7 specifies
602
 * that the padding used for a block cipher is a string of bytes,
603
 * each of whose value is the same as the length of the padding,
604
 * and that all data is padded.  (Even data that starts out with
605
 * an exact multiple of blocks gets added to it another block,
606
 * all of which is padding.)
607
 *
608
 * XXX I would kind of like to combine this with the function above
609
 * which does decryption, since they have a lot in common.  But the
610
 * tricky parts about padding and filling blocks would be much
611
 * harder to read that way, so I left them separate.  At least for
612
 * now until it is clear that they are right.
613
 */
614
SECStatus
615
sec_PKCS7Encrypt(sec_PKCS7CipherObject *obj, unsigned char *output,
616
                 unsigned int *output_len_p, unsigned int max_output_len,
617
                 const unsigned char *input, unsigned int input_len,
618
                 PRBool final)
619
0
{
620
0
    int blocks, bsize, padlen, pcount, padsize;
621
0
    unsigned int max_needed, ifraglen, ofraglen, output_len;
622
0
    unsigned char *pbuf;
623
0
    SECStatus rv;
624
625
0
    PORT_Assert(obj->encrypt);
626
627
    /*
628
     * Check that we have enough room for the output.  Our caller should
629
     * already handle this; failure is really an internal error (i.e. bug).
630
     */
631
0
    max_needed = sec_PKCS7EncryptLength(obj, input_len, final);
632
0
    PORT_Assert(max_output_len >= max_needed);
633
0
    if (max_output_len < max_needed) {
634
        /* PORT_SetError (XXX); */
635
0
        return SECFailure;
636
0
    }
637
638
0
    bsize = obj->block_size;
639
0
    padsize = obj->pad_size;
640
641
    /*
642
     * When no blocking and padding work to do, we can simply call the
643
     * cipher function and we are done.
644
     */
645
0
    if (bsize == 0) {
646
0
        return (*obj->doit)(obj->cx, output, output_len_p, max_output_len,
647
0
                            input, input_len);
648
0
    }
649
650
0
    pcount = obj->pending_count;
651
0
    pbuf = obj->pending_buf;
652
653
0
    output_len = 0;
654
655
0
    if (pcount) {
656
        /*
657
         * Try to fill in an entire block, starting with the bytes
658
         * we already have saved away.
659
         */
660
0
        while (input_len && pcount < bsize) {
661
0
            pbuf[pcount++] = *input++;
662
0
            input_len--;
663
0
        }
664
        /*
665
         * If we do not have a full block and we know we will be
666
         * called again, then we are done for now.
667
         */
668
0
        if (pcount < bsize && !final) {
669
0
            obj->pending_count = pcount;
670
0
            if (output_len_p != NULL)
671
0
                *output_len_p = 0;
672
0
            return SECSuccess;
673
0
        }
674
        /*
675
         * If we have a whole block available, encrypt it.
676
         */
677
0
        if ((padsize == 0) || (pcount % padsize) == 0) {
678
0
            rv = (*obj->doit)(obj->cx, output, &ofraglen, max_output_len,
679
0
                              pbuf, pcount);
680
0
            if (rv != SECSuccess)
681
0
                return rv;
682
683
            /*
684
             * For now anyway, all of our ciphers have the same number of
685
             * bytes of output as they do input.  If this ever becomes untrue,
686
             * then sec_PKCS7EncryptLength needs to be made smarter!
687
             */
688
0
            PORT_Assert(ofraglen == pcount);
689
690
            /*
691
             * Account for the bytes now in output.
692
             */
693
0
            max_output_len -= ofraglen;
694
0
            output_len += ofraglen;
695
0
            output += ofraglen;
696
697
0
            pcount = 0;
698
0
        }
699
0
    }
700
701
0
    if (input_len) {
702
0
        PORT_Assert(pcount == 0);
703
704
0
        blocks = input_len / bsize;
705
0
        ifraglen = blocks * bsize;
706
707
0
        if (ifraglen) {
708
0
            rv = (*obj->doit)(obj->cx, output, &ofraglen, max_output_len,
709
0
                              input, ifraglen);
710
0
            if (rv != SECSuccess)
711
0
                return rv;
712
713
            /*
714
             * For now anyway, all of our ciphers have the same number of
715
             * bytes of output as they do input.  If this ever becomes untrue,
716
             * then sec_PKCS7EncryptLength needs to be made smarter!
717
             */
718
0
            PORT_Assert(ifraglen == ofraglen);
719
720
0
            max_output_len -= ofraglen;
721
0
            output_len += ofraglen;
722
0
            output += ofraglen;
723
0
        }
724
725
0
        pcount = input_len - ifraglen;
726
0
        PORT_Assert(pcount < bsize);
727
0
        if (pcount)
728
0
            PORT_Memcpy(pbuf, input + ifraglen, pcount);
729
0
    }
730
731
0
    if (final) {
732
0
        if (padsize) {
733
0
            padlen = padsize - (pcount % padsize);
734
0
            PORT_Memset(pbuf + pcount, padlen, padlen);
735
0
        } else {
736
0
            padlen = 0;
737
0
        }
738
0
        rv = (*obj->doit)(obj->cx, output, &ofraglen, max_output_len,
739
0
                          pbuf, pcount + padlen);
740
0
        if (rv != SECSuccess)
741
0
            return rv;
742
743
        /*
744
         * For now anyway, all of our ciphers have the same number of
745
         * bytes of output as they do input.  If this ever becomes untrue,
746
         * then sec_PKCS7EncryptLength needs to be made smarter!
747
         */
748
0
        PORT_Assert(ofraglen == (pcount + padlen));
749
0
        output_len += ofraglen;
750
0
    } else {
751
0
        obj->pending_count = pcount;
752
0
    }
753
754
0
    PORT_Assert(output_len_p != NULL || output_len == 0);
755
0
    if (output_len_p != NULL)
756
0
        *output_len_p = output_len;
757
758
0
    return SECSuccess;
759
0
}
760
761
/*
762
 * End of cipher stuff.
763
 * -------------------------------------------------------------------
764
 */
765
766
/*
767
 * -------------------------------------------------------------------
768
 * XXX The following Attribute stuff really belongs elsewhere.
769
 * The Attribute type is *not* part of pkcs7 but rather X.501.
770
 * But for now, since PKCS7 is the only customer of attributes,
771
 * we define them here.  Once there is a use outside of PKCS7,
772
 * then change the attribute types and functions from internal
773
 * to external naming convention, and move them elsewhere!
774
 */
775
776
/*
777
 * Look through a set of attributes and find one that matches the
778
 * specified object ID.  If "only" is true, then make sure that
779
 * there is not more than one attribute of the same type.  Otherwise,
780
 * just return the first one found. (XXX Does anybody really want
781
 * that first-found behavior?  It was like that when I found it...)
782
 */
783
SEC_PKCS7Attribute *
784
sec_PKCS7FindAttribute(SEC_PKCS7Attribute **attrs, SECOidTag oidtag,
785
                       PRBool only)
786
0
{
787
0
    SECOidData *oid;
788
0
    SEC_PKCS7Attribute *attr1, *attr2;
789
790
0
    if (attrs == NULL)
791
0
        return NULL;
792
793
0
    oid = SECOID_FindOIDByTag(oidtag);
794
0
    if (oid == NULL)
795
0
        return NULL;
796
797
0
    while ((attr1 = *attrs++) != NULL) {
798
0
        if (attr1->type.len == oid->oid.len && PORT_Memcmp(attr1->type.data, oid->oid.data, oid->oid.len) == 0)
799
0
            break;
800
0
    }
801
802
0
    if (attr1 == NULL)
803
0
        return NULL;
804
805
0
    if (!only)
806
0
        return attr1;
807
808
0
    while ((attr2 = *attrs++) != NULL) {
809
0
        if (attr2->type.len == oid->oid.len && PORT_Memcmp(attr2->type.data, oid->oid.data, oid->oid.len) == 0)
810
0
            break;
811
0
    }
812
813
0
    if (attr2 != NULL)
814
0
        return NULL;
815
816
0
    return attr1;
817
0
}
818
819
/*
820
 * Return the single attribute value, doing some sanity checking first:
821
 * - Multiple values are *not* expected.
822
 * - Empty values are *not* expected.
823
 */
824
SECItem *
825
sec_PKCS7AttributeValue(SEC_PKCS7Attribute *attr)
826
0
{
827
0
    SECItem *value;
828
829
0
    if (attr == NULL)
830
0
        return NULL;
831
832
0
    value = attr->values[0];
833
834
0
    if (value == NULL || value->data == NULL || value->len == 0)
835
0
        return NULL;
836
837
0
    if (attr->values[1] != NULL)
838
0
        return NULL;
839
840
0
    return value;
841
0
}
842
843
static const SEC_ASN1Template *
844
sec_attr_choose_attr_value_template(void *src_or_dest, PRBool encoding)
845
0
{
846
0
    const SEC_ASN1Template *theTemplate;
847
848
0
    SEC_PKCS7Attribute *attribute;
849
0
    SECOidData *oiddata;
850
0
    PRBool encoded;
851
852
0
    PORT_Assert(src_or_dest != NULL);
853
0
    if (src_or_dest == NULL)
854
0
        return NULL;
855
856
0
    attribute = (SEC_PKCS7Attribute *)src_or_dest;
857
858
0
    if (encoding && attribute->encoded)
859
0
        return SEC_ASN1_GET(SEC_AnyTemplate);
860
861
0
    oiddata = attribute->typeTag;
862
0
    if (oiddata == NULL) {
863
0
        oiddata = SECOID_FindOID(&attribute->type);
864
0
        attribute->typeTag = oiddata;
865
0
    }
866
867
0
    if (oiddata == NULL) {
868
0
        encoded = PR_TRUE;
869
0
        theTemplate = SEC_ASN1_GET(SEC_AnyTemplate);
870
0
    } else {
871
0
        switch (oiddata->offset) {
872
0
            default:
873
0
                encoded = PR_TRUE;
874
0
                theTemplate = SEC_ASN1_GET(SEC_AnyTemplate);
875
0
                break;
876
0
            case SEC_OID_PKCS9_EMAIL_ADDRESS:
877
0
            case SEC_OID_RFC1274_MAIL:
878
0
            case SEC_OID_PKCS9_UNSTRUCTURED_NAME:
879
0
                encoded = PR_FALSE;
880
0
                theTemplate = SEC_ASN1_GET(SEC_IA5StringTemplate);
881
0
                break;
882
0
            case SEC_OID_PKCS9_CONTENT_TYPE:
883
0
                encoded = PR_FALSE;
884
0
                theTemplate = SEC_ASN1_GET(SEC_ObjectIDTemplate);
885
0
                break;
886
0
            case SEC_OID_PKCS9_MESSAGE_DIGEST:
887
0
                encoded = PR_FALSE;
888
0
                theTemplate = SEC_ASN1_GET(SEC_OctetStringTemplate);
889
0
                break;
890
0
            case SEC_OID_PKCS9_SIGNING_TIME:
891
0
                encoded = PR_FALSE;
892
0
                theTemplate = SEC_ASN1_GET(CERT_TimeChoiceTemplate);
893
0
                break;
894
                /* XXX Want other types here, too */
895
0
        }
896
0
    }
897
898
0
    if (encoding) {
899
        /*
900
         * If we are encoding and we think we have an already-encoded value,
901
         * then the code which initialized this attribute should have set
902
         * the "encoded" property to true (and we would have returned early,
903
         * up above).  No devastating error, but that code should be fixed.
904
         * (It could indicate that the resulting encoded bytes are wrong.)
905
         */
906
0
        PORT_Assert(!encoded);
907
0
    } else {
908
        /*
909
         * We are decoding; record whether the resulting value is
910
         * still encoded or not.
911
         */
912
0
        attribute->encoded = encoded;
913
0
    }
914
0
    return theTemplate;
915
0
}
916
917
static const SEC_ASN1TemplateChooserPtr sec_attr_chooser = sec_attr_choose_attr_value_template;
918
919
static const SEC_ASN1Template sec_pkcs7_attribute_template[] = {
920
    { SEC_ASN1_SEQUENCE,
921
      0, NULL, sizeof(SEC_PKCS7Attribute) },
922
    { SEC_ASN1_OBJECT_ID,
923
      offsetof(SEC_PKCS7Attribute, type) },
924
    { SEC_ASN1_DYNAMIC | SEC_ASN1_SET_OF,
925
      offsetof(SEC_PKCS7Attribute, values),
926
      &sec_attr_chooser },
927
    { 0 }
928
};
929
930
static const SEC_ASN1Template sec_pkcs7_set_of_attribute_template[] = {
931
    { SEC_ASN1_SET_OF, 0, sec_pkcs7_attribute_template },
932
};
933
934
/*
935
 * If you are wondering why this routine does not reorder the attributes
936
 * first, and might be tempted to make it do so, see the comment by the
937
 * call to ReorderAttributes in p7encode.c.  (Or, see who else calls this
938
 * and think long and hard about the implications of making it always
939
 * do the reordering.)
940
 */
941
SECItem *
942
sec_PKCS7EncodeAttributes(PLArenaPool *poolp, SECItem *dest, void *src)
943
0
{
944
0
    return SEC_ASN1EncodeItem(poolp, dest, src,
945
0
                              sec_pkcs7_set_of_attribute_template);
946
0
}
947
948
/*
949
 * Make sure that the order of the attributes guarantees valid DER
950
 * (which must be in lexigraphically ascending order for a SET OF);
951
 * if reordering is necessary it will be done in place (in attrs).
952
 */
953
SECStatus
954
sec_PKCS7ReorderAttributes(SEC_PKCS7Attribute **attrs)
955
0
{
956
0
    PLArenaPool *poolp;
957
0
    int num_attrs, i, pass, besti;
958
0
    unsigned int j;
959
0
    SECItem **enc_attrs;
960
0
    SEC_PKCS7Attribute **new_attrs;
961
962
    /*
963
     * I think we should not be called with NULL.  But if we are,
964
     * call it a success anyway, because the order *is* okay.
965
     */
966
0
    PORT_Assert(attrs != NULL);
967
0
    if (attrs == NULL)
968
0
        return SECSuccess;
969
970
    /*
971
     * Count how many attributes we are dealing with here.
972
     */
973
0
    num_attrs = 0;
974
0
    while (attrs[num_attrs] != NULL)
975
0
        num_attrs++;
976
977
    /*
978
     * Again, I think we should have some attributes here.
979
     * But if we do not, or if there is only one, then call it
980
     * a success because it also already has a fine order.
981
     */
982
0
    PORT_Assert(num_attrs);
983
0
    if (num_attrs == 0 || num_attrs == 1)
984
0
        return SECSuccess;
985
986
    /*
987
     * Allocate an arena for us to work with, so it is easy to
988
     * clean up all of the memory (fairly small pieces, really).
989
     */
990
0
    poolp = PORT_NewArena(1024); /* XXX what is right value? */
991
0
    if (poolp == NULL)
992
0
        return SECFailure; /* no memory; nothing we can do... */
993
994
    /*
995
     * Allocate arrays to hold the individual encodings which we will use
996
     * for comparisons and the reordered attributes as they are sorted.
997
     */
998
0
    enc_attrs = (SECItem **)PORT_ArenaZAlloc(poolp, num_attrs * sizeof(SECItem *));
999
0
    new_attrs = (SEC_PKCS7Attribute **)PORT_ArenaZAlloc(poolp,
1000
0
                                                        num_attrs * sizeof(SEC_PKCS7Attribute *));
1001
0
    if (enc_attrs == NULL || new_attrs == NULL) {
1002
0
        PORT_FreeArena(poolp, PR_FALSE);
1003
0
        return SECFailure;
1004
0
    }
1005
1006
    /*
1007
     * DER encode each individual attribute.
1008
     */
1009
0
    for (i = 0; i < num_attrs; i++) {
1010
0
        enc_attrs[i] = SEC_ASN1EncodeItem(poolp, NULL, attrs[i],
1011
0
                                          sec_pkcs7_attribute_template);
1012
0
        if (enc_attrs[i] == NULL) {
1013
0
            PORT_FreeArena(poolp, PR_FALSE);
1014
0
            return SECFailure;
1015
0
        }
1016
0
    }
1017
1018
    /*
1019
     * Now compare and sort them; this is not the most efficient sorting
1020
     * method, but it is just fine for the problem at hand, because the
1021
     * number of attributes is (always) going to be small.
1022
     */
1023
0
    for (pass = 0; pass < num_attrs; pass++) {
1024
        /*
1025
         * Find the first not-yet-accepted attribute.  (Once one is
1026
         * sorted into the other array, it is cleared from enc_attrs.)
1027
         */
1028
0
        for (i = 0; i < num_attrs; i++) {
1029
0
            if (enc_attrs[i] != NULL)
1030
0
                break;
1031
0
        }
1032
0
        PORT_Assert(i < num_attrs);
1033
0
        besti = i;
1034
1035
        /*
1036
         * Find the lowest (lexigraphically) encoding.  One that is
1037
         * shorter than all the rest is known to be "less" because each
1038
         * attribute is of the same type (a SEQUENCE) and so thus the
1039
         * first octet of each is the same, and the second octet is
1040
         * the length (or the length of the length with the high bit
1041
         * set, followed by the length, which also works out to always
1042
         * order the shorter first).  Two (or more) that have the
1043
         * same length need to be compared byte by byte until a mismatch
1044
         * is found.
1045
         */
1046
0
        for (i = besti + 1; i < num_attrs; i++) {
1047
0
            if (enc_attrs[i] == NULL) /* slot already handled */
1048
0
                continue;
1049
1050
0
            if (enc_attrs[i]->len != enc_attrs[besti]->len) {
1051
0
                if (enc_attrs[i]->len < enc_attrs[besti]->len)
1052
0
                    besti = i;
1053
0
                continue;
1054
0
            }
1055
1056
0
            for (j = 0; j < enc_attrs[i]->len; j++) {
1057
0
                if (enc_attrs[i]->data[j] < enc_attrs[besti]->data[j]) {
1058
0
                    besti = i;
1059
0
                    break;
1060
0
                }
1061
0
            }
1062
1063
            /*
1064
             * For this not to be true, we would have to have encountered
1065
             * two *identical* attributes, which I think we should not see.
1066
             * So assert if it happens, but even if it does, let it go
1067
             * through; the ordering of the two does not matter.
1068
             */
1069
0
            PORT_Assert(j < enc_attrs[i]->len);
1070
0
        }
1071
1072
        /*
1073
         * Now we have found the next-lowest one; copy it over and
1074
         * remove it from enc_attrs.
1075
         */
1076
0
        new_attrs[pass] = attrs[besti];
1077
0
        enc_attrs[besti] = NULL;
1078
0
    }
1079
1080
    /*
1081
     * Now new_attrs has the attributes in the order we want;
1082
     * copy them back into the attrs array we started with.
1083
     */
1084
0
    for (i = 0; i < num_attrs; i++)
1085
0
        attrs[i] = new_attrs[i];
1086
1087
0
    PORT_FreeArena(poolp, PR_FALSE);
1088
0
    return SECSuccess;
1089
0
}
1090
1091
/*
1092
 * End of attribute stuff.
1093
 * -------------------------------------------------------------------
1094
 */
1095
1096
/*
1097
 * Templates and stuff.  Keep these at the end of the file.
1098
 */
1099
1100
/* forward declaration */
1101
static const SEC_ASN1Template *
1102
sec_pkcs7_choose_content_template(void *src_or_dest, PRBool encoding);
1103
1104
static const SEC_ASN1TemplateChooserPtr sec_pkcs7_chooser = sec_pkcs7_choose_content_template;
1105
1106
const SEC_ASN1Template sec_PKCS7ContentInfoTemplate[] = {
1107
    { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
1108
      0, NULL, sizeof(SEC_PKCS7ContentInfo) },
1109
    { SEC_ASN1_OBJECT_ID,
1110
      offsetof(SEC_PKCS7ContentInfo, contentType) },
1111
    { SEC_ASN1_OPTIONAL | SEC_ASN1_DYNAMIC | SEC_ASN1_MAY_STREAM | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
1112
      offsetof(SEC_PKCS7ContentInfo, content),
1113
      &sec_pkcs7_chooser },
1114
    { 0 }
1115
};
1116
1117
/* XXX These names should change from external to internal convention. */
1118
1119
static const SEC_ASN1Template SEC_PKCS7SignerInfoTemplate[] = {
1120
    { SEC_ASN1_SEQUENCE,
1121
      0, NULL, sizeof(SEC_PKCS7SignerInfo) },
1122
    { SEC_ASN1_INTEGER,
1123
      offsetof(SEC_PKCS7SignerInfo, version) },
1124
    { SEC_ASN1_POINTER | SEC_ASN1_XTRN,
1125
      offsetof(SEC_PKCS7SignerInfo, issuerAndSN),
1126
      SEC_ASN1_SUB(CERT_IssuerAndSNTemplate) },
1127
    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
1128
      offsetof(SEC_PKCS7SignerInfo, digestAlg),
1129
      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
1130
    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
1131
      offsetof(SEC_PKCS7SignerInfo, authAttr),
1132
      sec_pkcs7_set_of_attribute_template },
1133
    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
1134
      offsetof(SEC_PKCS7SignerInfo, digestEncAlg),
1135
      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
1136
    { SEC_ASN1_OCTET_STRING,
1137
      offsetof(SEC_PKCS7SignerInfo, encDigest) },
1138
    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
1139
      offsetof(SEC_PKCS7SignerInfo, unAuthAttr),
1140
      sec_pkcs7_set_of_attribute_template },
1141
    { 0 }
1142
};
1143
1144
static const SEC_ASN1Template SEC_PKCS7SignedDataTemplate[] = {
1145
    { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
1146
      0, NULL, sizeof(SEC_PKCS7SignedData) },
1147
    { SEC_ASN1_INTEGER,
1148
      offsetof(SEC_PKCS7SignedData, version) },
1149
    { SEC_ASN1_SET_OF | SEC_ASN1_XTRN,
1150
      offsetof(SEC_PKCS7SignedData, digestAlgorithms),
1151
      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
1152
    { SEC_ASN1_INLINE,
1153
      offsetof(SEC_PKCS7SignedData, contentInfo),
1154
      sec_PKCS7ContentInfoTemplate },
1155
    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
1156
          SEC_ASN1_XTRN | 0,
1157
      offsetof(SEC_PKCS7SignedData, rawCerts),
1158
      SEC_ASN1_SUB(SEC_SetOfAnyTemplate) },
1159
    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
1160
          SEC_ASN1_XTRN | 1,
1161
      offsetof(SEC_PKCS7SignedData, crls),
1162
      SEC_ASN1_SUB(CERT_SetOfSignedCrlTemplate) },
1163
    { SEC_ASN1_SET_OF,
1164
      offsetof(SEC_PKCS7SignedData, signerInfos),
1165
      SEC_PKCS7SignerInfoTemplate },
1166
    { 0 }
1167
};
1168
1169
static const SEC_ASN1Template SEC_PointerToPKCS7SignedDataTemplate[] = {
1170
    { SEC_ASN1_POINTER, 0, SEC_PKCS7SignedDataTemplate }
1171
};
1172
1173
static const SEC_ASN1Template SEC_PKCS7RecipientInfoTemplate[] = {
1174
    { SEC_ASN1_SEQUENCE,
1175
      0, NULL, sizeof(SEC_PKCS7RecipientInfo) },
1176
    { SEC_ASN1_INTEGER,
1177
      offsetof(SEC_PKCS7RecipientInfo, version) },
1178
    { SEC_ASN1_POINTER | SEC_ASN1_XTRN,
1179
      offsetof(SEC_PKCS7RecipientInfo, issuerAndSN),
1180
      SEC_ASN1_SUB(CERT_IssuerAndSNTemplate) },
1181
    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
1182
      offsetof(SEC_PKCS7RecipientInfo, keyEncAlg),
1183
      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
1184
    { SEC_ASN1_OCTET_STRING,
1185
      offsetof(SEC_PKCS7RecipientInfo, encKey) },
1186
    { 0 }
1187
};
1188
1189
static const SEC_ASN1Template SEC_PKCS7EncryptedContentInfoTemplate[] = {
1190
    { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
1191
      0, NULL, sizeof(SEC_PKCS7EncryptedContentInfo) },
1192
    { SEC_ASN1_OBJECT_ID,
1193
      offsetof(SEC_PKCS7EncryptedContentInfo, contentType) },
1194
    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
1195
      offsetof(SEC_PKCS7EncryptedContentInfo, contentEncAlg),
1196
      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
1197
    { SEC_ASN1_OPTIONAL | SEC_ASN1_MAY_STREAM | SEC_ASN1_CONTEXT_SPECIFIC |
1198
          SEC_ASN1_XTRN | 0,
1199
      offsetof(SEC_PKCS7EncryptedContentInfo, encContent),
1200
      SEC_ASN1_SUB(SEC_OctetStringTemplate) },
1201
    { 0 }
1202
};
1203
1204
static const SEC_ASN1Template SEC_PKCS7EnvelopedDataTemplate[] = {
1205
    { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
1206
      0, NULL, sizeof(SEC_PKCS7EnvelopedData) },
1207
    { SEC_ASN1_INTEGER,
1208
      offsetof(SEC_PKCS7EnvelopedData, version) },
1209
    { SEC_ASN1_SET_OF,
1210
      offsetof(SEC_PKCS7EnvelopedData, recipientInfos),
1211
      SEC_PKCS7RecipientInfoTemplate },
1212
    { SEC_ASN1_INLINE,
1213
      offsetof(SEC_PKCS7EnvelopedData, encContentInfo),
1214
      SEC_PKCS7EncryptedContentInfoTemplate },
1215
    { 0 }
1216
};
1217
1218
static const SEC_ASN1Template SEC_PointerToPKCS7EnvelopedDataTemplate[] = {
1219
    { SEC_ASN1_POINTER, 0, SEC_PKCS7EnvelopedDataTemplate }
1220
};
1221
1222
static const SEC_ASN1Template SEC_PKCS7SignedAndEnvelopedDataTemplate[] = {
1223
    { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
1224
      0, NULL, sizeof(SEC_PKCS7SignedAndEnvelopedData) },
1225
    { SEC_ASN1_INTEGER,
1226
      offsetof(SEC_PKCS7SignedAndEnvelopedData, version) },
1227
    { SEC_ASN1_SET_OF,
1228
      offsetof(SEC_PKCS7SignedAndEnvelopedData, recipientInfos),
1229
      SEC_PKCS7RecipientInfoTemplate },
1230
    { SEC_ASN1_SET_OF | SEC_ASN1_XTRN,
1231
      offsetof(SEC_PKCS7SignedAndEnvelopedData, digestAlgorithms),
1232
      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
1233
    { SEC_ASN1_INLINE,
1234
      offsetof(SEC_PKCS7SignedAndEnvelopedData, encContentInfo),
1235
      SEC_PKCS7EncryptedContentInfoTemplate },
1236
    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
1237
          SEC_ASN1_XTRN | 0,
1238
      offsetof(SEC_PKCS7SignedAndEnvelopedData, rawCerts),
1239
      SEC_ASN1_SUB(SEC_SetOfAnyTemplate) },
1240
    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
1241
          SEC_ASN1_XTRN | 1,
1242
      offsetof(SEC_PKCS7SignedAndEnvelopedData, crls),
1243
      SEC_ASN1_SUB(CERT_SetOfSignedCrlTemplate) },
1244
    { SEC_ASN1_SET_OF,
1245
      offsetof(SEC_PKCS7SignedAndEnvelopedData, signerInfos),
1246
      SEC_PKCS7SignerInfoTemplate },
1247
    { 0 }
1248
};
1249
1250
static const SEC_ASN1Template
1251
    SEC_PointerToPKCS7SignedAndEnvelopedDataTemplate[] = {
1252
        { SEC_ASN1_POINTER, 0, SEC_PKCS7SignedAndEnvelopedDataTemplate }
1253
    };
1254
1255
static const SEC_ASN1Template SEC_PKCS7DigestedDataTemplate[] = {
1256
    { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
1257
      0, NULL, sizeof(SEC_PKCS7DigestedData) },
1258
    { SEC_ASN1_INTEGER,
1259
      offsetof(SEC_PKCS7DigestedData, version) },
1260
    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
1261
      offsetof(SEC_PKCS7DigestedData, digestAlg),
1262
      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
1263
    { SEC_ASN1_INLINE,
1264
      offsetof(SEC_PKCS7DigestedData, contentInfo),
1265
      sec_PKCS7ContentInfoTemplate },
1266
    { SEC_ASN1_OCTET_STRING,
1267
      offsetof(SEC_PKCS7DigestedData, digest) },
1268
    { 0 }
1269
};
1270
1271
static const SEC_ASN1Template SEC_PointerToPKCS7DigestedDataTemplate[] = {
1272
    { SEC_ASN1_POINTER, 0, SEC_PKCS7DigestedDataTemplate }
1273
};
1274
1275
static const SEC_ASN1Template SEC_PKCS7EncryptedDataTemplate[] = {
1276
    { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
1277
      0, NULL, sizeof(SEC_PKCS7EncryptedData) },
1278
    { SEC_ASN1_INTEGER,
1279
      offsetof(SEC_PKCS7EncryptedData, version) },
1280
    { SEC_ASN1_INLINE,
1281
      offsetof(SEC_PKCS7EncryptedData, encContentInfo),
1282
      SEC_PKCS7EncryptedContentInfoTemplate },
1283
    { 0 }
1284
};
1285
1286
static const SEC_ASN1Template SEC_PointerToPKCS7EncryptedDataTemplate[] = {
1287
    { SEC_ASN1_POINTER, 0, SEC_PKCS7EncryptedDataTemplate }
1288
};
1289
1290
static const SEC_ASN1Template *
1291
sec_pkcs7_choose_content_template(void *src_or_dest, PRBool encoding)
1292
5.75k
{
1293
5.75k
    const SEC_ASN1Template *theTemplate;
1294
5.75k
    SEC_PKCS7ContentInfo *cinfo;
1295
5.75k
    SECOidTag kind;
1296
1297
5.75k
    PORT_Assert(src_or_dest != NULL);
1298
5.75k
    if (src_or_dest == NULL)
1299
0
        return NULL;
1300
1301
5.75k
    cinfo = (SEC_PKCS7ContentInfo *)src_or_dest;
1302
5.75k
    kind = SEC_PKCS7ContentType(cinfo);
1303
5.75k
    switch (kind) {
1304
163
        default:
1305
163
            theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
1306
163
            break;
1307
182
        case SEC_OID_PKCS7_DATA:
1308
182
            theTemplate = SEC_ASN1_GET(SEC_PointerToOctetStringTemplate);
1309
182
            break;
1310
0
        case SEC_OID_PKCS7_SIGNED_DATA:
1311
0
            theTemplate = SEC_PointerToPKCS7SignedDataTemplate;
1312
0
            break;
1313
0
        case SEC_OID_PKCS7_ENVELOPED_DATA:
1314
0
            theTemplate = SEC_PointerToPKCS7EnvelopedDataTemplate;
1315
0
            break;
1316
0
        case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
1317
0
            theTemplate = SEC_PointerToPKCS7SignedAndEnvelopedDataTemplate;
1318
0
            break;
1319
0
        case SEC_OID_PKCS7_DIGESTED_DATA:
1320
0
            theTemplate = SEC_PointerToPKCS7DigestedDataTemplate;
1321
0
            break;
1322
5.40k
        case SEC_OID_PKCS7_ENCRYPTED_DATA:
1323
5.40k
            theTemplate = SEC_PointerToPKCS7EncryptedDataTemplate;
1324
5.40k
            break;
1325
5.75k
    }
1326
5.75k
    return theTemplate;
1327
5.75k
}
1328
1329
/*
1330
 * End of templates.  Do not add stuff after this; put new code
1331
 * up above the start of the template definitions.
1332
 */