Coverage Report

Created: 2018-09-25 14:53

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