1
/* ***** BEGIN LICENSE BLOCK *****
2
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
* The contents of this file are subject to the Mozilla Public License Version
5
* 1.1 (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
7
* http://www.mozilla.org/MPL/
9
* Software distributed under the License is distributed on an "AS IS" basis,
10
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
* for the specific language governing rights and limitations under the
14
* The Original Code is the Netscape security libraries.
16
* The Initial Developer of the Original Code is
17
* Netscape Communications Corporation.
18
* Portions created by the Initial Developer are Copyright (C) 1994-2000
19
* the Initial Developer. All Rights Reserved.
22
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
24
* Alternatively, the contents of this file may be used under the terms of
25
* either the GNU General Public License Version 2 or later (the "GPL"), or
26
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
* in which case the provisions of the GPL or the LGPL are applicable instead
28
* of those above. If you wish to allow use of your version of this file only
29
* under the terms of either the GPL or the LGPL, and not to allow others to
30
* use your version of this file under the terms of the MPL, indicate your
31
* decision by deleting the provisions above and replace them with the notice
32
* and other provisions required by the GPL or the LGPL. If you do not delete
33
* the provisions above, a recipient may use your version of this file under
34
* the terms of any one of the MPL, the GPL or the LGPL.
36
* ***** END LICENSE BLOCK ***** */
39
* PKCS7 decoding, verification.
41
* $Id: p7decode.c,v 1.20.2.1 2006/04/28 03:35:30 rrelyea%redhat.com Exp $
49
/* XXX do not want to have to include */
50
#include "certdb.h" /* certdb.h -- the trust stuff needed by */
51
/* the add certificate code needs to get */
52
/* rewritten/abstracted and then this */
53
/* include should be removed! */
54
/*#include "cdbhdl.h" */
63
#include "sechash.h" /* for HASH_GetHashObject() */
67
struct sec_pkcs7_decoder_worker {
71
const SECHashObject **digobjs;
72
sec_PKCS7CipherObject *decryptobj;
76
struct SEC_PKCS7DecoderContextStr {
77
SEC_ASN1DecoderContext *dcx;
78
SEC_PKCS7ContentInfo *cinfo;
79
SEC_PKCS7DecoderContentCallback cb;
81
SECKEYGetPasswordKey pwfn;
83
struct sec_pkcs7_decoder_worker worker;
84
PRArenaPool *tmp_poolp;
86
SEC_PKCS7GetDecryptKeyCallback dkcb;
88
SEC_PKCS7DecryptionAllowedCallback decrypt_allowed_cb;
92
* Handle one worker, decrypting and digesting the data as necessary.
94
* XXX If/when we support nested contents, this probably needs to be
95
* revised somewhat to get passed the content-info (which unfortunately
96
* can be two different types depending on whether it is encrypted or not)
97
* corresponding to the given worker.
100
sec_pkcs7_decoder_work_data (SEC_PKCS7DecoderContext *p7dcx,
101
struct sec_pkcs7_decoder_worker *worker,
102
const unsigned char *data, unsigned long len,
105
unsigned char *buf = NULL;
110
* We should really have data to process, or we should be trying
111
* to finish/flush the last block. (This is an overly paranoid
112
* check since all callers are in this file and simple inspection
113
* proves they do it right. But it could find a bug in future
114
* modifications/development, that is why it is here.)
116
PORT_Assert ((data != NULL && len) || final);
119
* Decrypt this chunk.
121
* XXX If we get an error, we do not want to do the digest or callback,
122
* but we want to keep decoding. Or maybe we want to stop decoding
123
* altogether if there is a callback, because obviously we are not
124
* sending the data back and they want to know that.
126
if (worker->decryptobj != NULL) {
127
/* XXX the following lengths should all be longs? */
128
unsigned int inlen; /* length of data being decrypted */
129
unsigned int outlen; /* length of decrypted data */
130
unsigned int buflen; /* length available for decrypted data */
134
buflen = sec_PKCS7DecryptLength (worker->decryptobj, inlen, final);
136
if (inlen == 0) /* no input and no output */
139
* No output is expected, but the input data may be buffered
140
* so we still have to call Decrypt.
142
rv = sec_PKCS7Decrypt (worker->decryptobj, NULL, NULL, 0,
144
if (rv != SECSuccess) {
145
p7dcx->error = PORT_GetError();
146
return; /* XXX indicate error? */
151
if (p7dcx->cb != NULL) {
152
buf = (unsigned char *) PORT_Alloc (buflen);
155
unsigned long oldlen;
158
* XXX This assumes one level of content only.
159
* See comment above about nested content types.
160
* XXX Also, it should work for signedAndEnvelopedData, too!
162
plain = &(p7dcx->cinfo->
163
content.envelopedData->encContentInfo.plainContent);
167
buf = (unsigned char*)PORT_ArenaAlloc (p7dcx->cinfo->poolp,
170
buf = (unsigned char*)PORT_ArenaGrow (p7dcx->cinfo->poolp,
172
oldlen, oldlen + buflen);
179
p7dcx->error = SEC_ERROR_NO_MEMORY;
180
return; /* XXX indicate error? */
182
rv = sec_PKCS7Decrypt (worker->decryptobj, buf, &outlen, buflen,
184
if (rv != SECSuccess) {
185
p7dcx->error = PORT_GetError();
186
return; /* XXX indicate error? */
189
PORT_Assert (final || outlen == buflen);
190
plain->len += outlen;
197
* Update the running digests.
200
for (i = 0; i < worker->digcnt; i++) {
201
(* worker->digobjs[i]->update) (worker->digcxs[i], data, len);
206
* Pass back the contents bytes, and free the temporary buffer.
208
if (p7dcx->cb != NULL) {
210
(* p7dcx->cb) (p7dcx->cb_arg, (const char *)data, len);
211
if (worker->decryptobj != NULL) {
212
PORT_Assert (buf != NULL);
219
sec_pkcs7_decoder_filter (void *arg, const char *data, unsigned long len,
220
int depth, SEC_ASN1EncodingPart data_kind)
222
SEC_PKCS7DecoderContext *p7dcx;
223
struct sec_pkcs7_decoder_worker *worker;
226
* Since we do not handle any nested contents, the only bytes we
227
* are really interested in are the actual contents bytes (not
228
* the identifier, length, or end-of-contents bytes). If we were
229
* handling nested types we would probably need to do something
230
* smarter based on depth and data_kind.
232
if (data_kind != SEC_ASN1_Contents)
236
* The ASN.1 decoder should not even call us with a length of 0.
237
* Just being paranoid.
243
p7dcx = (SEC_PKCS7DecoderContext*)arg;
246
* Handling nested contents would mean that there is a chain
247
* of workers -- one per each level of content. The following
248
* would start with the first worker and loop over them.
250
worker = &(p7dcx->worker);
252
worker->saw_contents = PR_TRUE;
254
sec_pkcs7_decoder_work_data (p7dcx, worker,
255
(const unsigned char *) data, len, PR_FALSE);
260
* Create digest contexts for each algorithm in "digestalgs".
261
* No algorithms is not an error, we just do not do anything.
262
* An error (like trouble allocating memory), marks the error
263
* in "p7dcx" and returns SECFailure, which means that our caller
264
* should just give up altogether.
267
sec_pkcs7_decoder_start_digests (SEC_PKCS7DecoderContext *p7dcx, int depth,
268
SECAlgorithmID **digestalgs)
272
if (digestalgs == NULL)
276
* Count the algorithms.
279
while (digestalgs[digcnt] != NULL)
283
* No algorithms means no work to do.
284
* Just act as if there were no algorithms specified.
289
p7dcx->worker.digcxs = (void**)PORT_ArenaAlloc (p7dcx->tmp_poolp,
290
digcnt * sizeof (void *));
291
p7dcx->worker.digobjs = (const SECHashObject**)PORT_ArenaAlloc (p7dcx->tmp_poolp,
292
digcnt * sizeof (SECHashObject *));
293
if (p7dcx->worker.digcxs == NULL || p7dcx->worker.digobjs == NULL) {
294
p7dcx->error = SEC_ERROR_NO_MEMORY;
298
p7dcx->worker.depth = depth;
299
p7dcx->worker.digcnt = 0;
302
* Create a digest context for each algorithm.
304
for (i = 0; i < digcnt; i++) {
305
SECAlgorithmID * algid = digestalgs[i];
306
SECOidTag oidTag = SECOID_FindOIDTag(&(algid->algorithm));
307
const SECHashObject *digobj = HASH_GetHashObjectByOidTag(oidTag);
311
* Skip any algorithm we do not even recognize; obviously,
312
* this could be a problem, but if it is critical then the
313
* result will just be that the signature does not verify.
314
* We do not necessarily want to error out here, because
315
* the particular algorithm may not actually be important,
316
* but we cannot know that until later.
318
if (digobj == NULL) {
319
p7dcx->worker.digcnt--;
323
digcx = (* digobj->create)();
325
(* digobj->begin) (digcx);
326
p7dcx->worker.digobjs[p7dcx->worker.digcnt] = digobj;
327
p7dcx->worker.digcxs[p7dcx->worker.digcnt] = digcx;
328
p7dcx->worker.digcnt++;
332
if (p7dcx->worker.digcnt != 0)
333
SEC_ASN1DecoderSetFilterProc (p7dcx->dcx,
334
sec_pkcs7_decoder_filter,
336
(PRBool)(p7dcx->cb != NULL));
342
* Close out all of the digest contexts, storing the results in "digestsp".
345
sec_pkcs7_decoder_finish_digests (SEC_PKCS7DecoderContext *p7dcx,
349
struct sec_pkcs7_decoder_worker *worker;
350
const SECHashObject *digobj;
352
SECItem **digests, *digest;
357
* XXX Handling nested contents would mean that there is a chain
358
* of workers -- one per each level of content. The following
359
* would want to find the last worker in the chain.
361
worker = &(p7dcx->worker);
364
* If no digests, then we have nothing to do.
366
if (worker->digcnt == 0)
370
* No matter what happens after this, we want to stop filtering.
371
* XXX If we handle nested contents, we only want to stop filtering
372
* if we are finishing off the *last* worker.
374
SEC_ASN1DecoderClearFilterProc (p7dcx->dcx);
377
* If we ended up with no contents, just destroy each
378
* digest context -- they are meaningless and potentially
379
* confusing, because their presence would imply some content
382
if (! worker->saw_contents) {
383
for (i = 0; i < worker->digcnt; i++) {
384
digcx = worker->digcxs[i];
385
digobj = worker->digobjs[i];
386
(* digobj->destroy) (digcx, PR_TRUE);
391
mark = PORT_ArenaMark (poolp);
394
* Close out each digest context, saving digest away.
397
(SECItem**)PORT_ArenaAlloc (poolp,(worker->digcnt+1)*sizeof(SECItem *));
398
digest = (SECItem*)PORT_ArenaAlloc (poolp, worker->digcnt*sizeof(SECItem));
399
if (digests == NULL || digest == NULL) {
400
p7dcx->error = PORT_GetError();
401
PORT_ArenaRelease (poolp, mark);
405
for (i = 0; i < worker->digcnt; i++, digest++) {
406
digcx = worker->digcxs[i];
407
digobj = worker->digobjs[i];
409
digest->data = (unsigned char*)PORT_ArenaAlloc (poolp, digobj->length);
410
if (digest->data == NULL) {
411
p7dcx->error = PORT_GetError();
412
PORT_ArenaRelease (poolp, mark);
416
digest->len = digobj->length;
417
(* digobj->end) (digcx, digest->data, &(digest->len), digest->len);
418
(* digobj->destroy) (digcx, PR_TRUE);
425
PORT_ArenaUnmark (poolp, mark);
430
* XXX Need comment explaining following helper function (which is used
431
* by sec_pkcs7_decoder_start_decrypt).
433
extern const SEC_ASN1Template SEC_SMIMEKEAParamTemplateAllParams[];
436
sec_pkcs7_decoder_get_recipient_key (SEC_PKCS7DecoderContext *p7dcx,
437
SEC_PKCS7RecipientInfo **recipientinfos,
438
SEC_PKCS7EncryptedContentInfo *enccinfo)
440
SEC_PKCS7RecipientInfo *ri;
441
CERTCertificate *cert = NULL;
442
SECKEYPrivateKey *privkey = NULL;
444
SECOidTag keyalgtag, bulkalgtag, encalgtag;
448
if (recipientinfos == NULL || recipientinfos[0] == NULL) {
449
p7dcx->error = SEC_ERROR_NOT_A_RECIPIENT;
453
cert = PK11_FindCertAndKeyByRecipientList(&slot,recipientinfos,&ri,
454
&privkey, p7dcx->pwfn_arg);
456
p7dcx->error = SEC_ERROR_NOT_A_RECIPIENT;
460
ri->cert = cert; /* so we can find it later */
461
PORT_Assert(privkey != NULL);
463
keyalgtag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm));
464
encalgtag = SECOID_GetAlgorithmTag (&(ri->keyEncAlg));
465
if ((encalgtag != SEC_OID_NETSCAPE_SMIME_KEA) && (keyalgtag != encalgtag)) {
466
p7dcx->error = SEC_ERROR_PKCS7_KEYALG_MISMATCH;
469
bulkalgtag = SECOID_GetAlgorithmTag (&(enccinfo->contentEncAlg));
472
case SEC_OID_PKCS1_RSA_ENCRYPTION:
473
bulkkey = PK11_PubUnwrapSymKey (privkey, &ri->encKey,
474
PK11_AlgtagToMechanism (bulkalgtag),
476
if (bulkkey == NULL) {
477
p7dcx->error = PORT_GetError();
482
/* ### mwelch -- KEA */
483
case SEC_OID_NETSCAPE_SMIME_KEA:
486
CK_MECHANISM_TYPE bulkType;
488
SECKEYPublicKey *senderPubKey;
489
SEC_PKCS7SMIMEKEAParameters keaParams;
491
(void) memset(&keaParams, 0, sizeof(keaParams));
493
/* Decode the KEA algorithm parameters. */
494
err = SEC_ASN1DecodeItem(NULL,
496
SEC_SMIMEKEAParamTemplateAllParams,
497
&(ri->keyEncAlg.parameters));
498
if (err != SECSuccess)
506
/* We just got key data, no key structure. So, we
509
PK11_MakeKEAPubKey(keaParams.originatorKEAKey.data,
510
keaParams.originatorKEAKey.len);
511
if (senderPubKey == NULL)
513
p7dcx->error = PORT_GetError();
518
/* Generate the TEK (token exchange key) which we use
519
to unwrap the bulk encryption key. */
520
tek = PK11_PubDerive(privkey, senderPubKey,
522
&keaParams.originatorRA,
524
CKM_KEA_KEY_DERIVE, CKM_SKIPJACK_WRAP,
525
CKA_WRAP, 0, p7dcx->pwfn_arg);
526
SECKEY_DestroyPublicKey(senderPubKey);
530
p7dcx->error = PORT_GetError();
535
/* Now that we have the TEK, unwrap the bulk key
536
with which to decrypt the message. We have to
537
do one of two different things depending on
538
whether Skipjack was used for bulk encryption
540
bulkType = PK11_AlgtagToMechanism (bulkalgtag);
543
case CKM_SKIPJACK_CBC64:
544
case CKM_SKIPJACK_ECB64:
545
case CKM_SKIPJACK_OFB64:
546
case CKM_SKIPJACK_CFB64:
547
case CKM_SKIPJACK_CFB32:
548
case CKM_SKIPJACK_CFB16:
549
case CKM_SKIPJACK_CFB8:
550
/* Skipjack is being used as the bulk encryption algorithm.*/
551
/* Unwrap the bulk key. */
552
bulkkey = PK11_UnwrapSymKey(tek, CKM_SKIPJACK_WRAP,
558
/* Skipjack was not used for bulk encryption of this
559
message. Use Skipjack CBC64, with the nonSkipjackIV
560
part of the KEA key parameters, to decrypt
561
the bulk key. If we got a parameter indicating that the
562
bulk key size is different than the encrypted key size,
563
pass in the real key size. */
565
/* Check for specified bulk key length (unspecified implies
566
that the bulk key length is the same as encrypted length) */
567
if (keaParams.bulkKeySize.len > 0)
569
p7dcx->error = SEC_ASN1DecodeItem(NULL, &bulkLength,
570
SEC_ASN1_GET(SEC_IntegerTemplate),
571
&keaParams.bulkKeySize);
574
if (p7dcx->error != SECSuccess)
577
bulkkey = PK11_UnwrapSymKey(tek, CKM_SKIPJACK_CBC64,
578
&keaParams.nonSkipjackIV,
581
CKA_DECRYPT, bulkLength);
587
p7dcx->error = PORT_GetError();
594
p7dcx->error = SEC_ERROR_UNSUPPORTED_KEYALG;
602
SECKEY_DestroyPrivateKey (privkey);
608
* XXX The following comment is old -- the function used to only handle
609
* EnvelopedData or SignedAndEnvelopedData but now handles EncryptedData
610
* as well (and it had all of the code of the helper function above
611
* built into it), though the comment was left as is. Fix it...
613
* We are just about to decode the content of an EnvelopedData.
614
* Set up a decryption context so we can decrypt as we go.
615
* Presumably we are one of the recipients listed in "recipientinfos".
616
* (XXX And if we are not, or if we have trouble, what should we do?
617
* It would be nice to let the decoding still work. Maybe it should
618
* be an error if there is a content callback, but not an error otherwise?)
619
* The encryption key and related information can be found in "enccinfo".
622
sec_pkcs7_decoder_start_decrypt (SEC_PKCS7DecoderContext *p7dcx, int depth,
623
SEC_PKCS7RecipientInfo **recipientinfos,
624
SEC_PKCS7EncryptedContentInfo *enccinfo,
625
PK11SymKey **copy_key_for_signature)
627
PK11SymKey *bulkkey = NULL;
628
sec_PKCS7CipherObject *decryptobj;
631
* If a callback is supplied to retrieve the encryption key,
632
* for instance, for Encrypted Content infos, then retrieve
633
* the bulkkey from the callback. Otherwise, assume that
634
* we are processing Enveloped or SignedAndEnveloped data
637
* XXX Put an assert here?
639
if (SEC_PKCS7ContentType(p7dcx->cinfo) == SEC_OID_PKCS7_ENCRYPTED_DATA) {
640
if (p7dcx->dkcb != NULL) {
641
bulkkey = (*p7dcx->dkcb)(p7dcx->dkcb_arg,
642
&(enccinfo->contentEncAlg));
644
enccinfo->keysize = 0;
646
bulkkey = sec_pkcs7_decoder_get_recipient_key (p7dcx, recipientinfos,
648
if (bulkkey == NULL) goto no_decryption;
649
enccinfo->keysize = PK11_GetKeyStrength(bulkkey,
650
&(enccinfo->contentEncAlg));
655
* XXX I think following should set error in p7dcx and clear set error
656
* (as used to be done here, or as is done in get_receipient_key above.
658
if(bulkkey == NULL) {
663
* We want to make sure decryption is allowed. This is done via
664
* a callback specified in SEC_PKCS7DecoderStart().
666
if (p7dcx->decrypt_allowed_cb) {
667
if ((*p7dcx->decrypt_allowed_cb) (&(enccinfo->contentEncAlg),
668
bulkkey) == PR_FALSE) {
669
p7dcx->error = SEC_ERROR_DECRYPTION_DISALLOWED;
673
p7dcx->error = SEC_ERROR_DECRYPTION_DISALLOWED;
678
* When decrypting a signedAndEnvelopedData, the signature also has
679
* to be decrypted with the bulk encryption key; to avoid having to
680
* get it all over again later (and do another potentially expensive
681
* RSA operation), copy it for later signature verification to use.
683
if (copy_key_for_signature != NULL)
684
*copy_key_for_signature = PK11_ReferenceSymKey (bulkkey);
687
* Now we have the bulk encryption key (in bulkkey) and the
688
* the algorithm (in enccinfo->contentEncAlg). Using those,
689
* create a decryption context.
691
decryptobj = sec_PKCS7CreateDecryptObject (bulkkey,
692
&(enccinfo->contentEncAlg));
695
* We are done with (this) bulkkey now.
697
PK11_FreeSymKey (bulkkey);
699
if (decryptobj == NULL) {
700
p7dcx->error = PORT_GetError();
705
SEC_ASN1DecoderSetFilterProc (p7dcx->dcx,
706
sec_pkcs7_decoder_filter,
708
(PRBool)(p7dcx->cb != NULL));
710
p7dcx->worker.depth = depth;
711
p7dcx->worker.decryptobj = decryptobj;
717
* For some reason (error set already, if appropriate), we cannot
718
* decrypt the content. I am not sure what exactly is the right
719
* thing to do here; in some cases we want to just stop, and in
720
* others we want to let the decoding finish even though we cannot
721
* decrypt the content. My current thinking is that if the caller
722
* set up a content callback, then they are really interested in
723
* getting (decrypted) content, and if they cannot they will want
724
* to know about it. However, if no callback was specified, then
725
* maybe it is not important that the decryption failed.
727
if (p7dcx->cb != NULL)
730
return SECSuccess; /* Let the decoding continue. */
735
sec_pkcs7_decoder_finish_decrypt (SEC_PKCS7DecoderContext *p7dcx,
737
SEC_PKCS7EncryptedContentInfo *enccinfo)
739
struct sec_pkcs7_decoder_worker *worker;
742
* XXX Handling nested contents would mean that there is a chain
743
* of workers -- one per each level of content. The following
744
* would want to find the last worker in the chain.
746
worker = &(p7dcx->worker);
749
* If no decryption context, then we have nothing to do.
751
if (worker->decryptobj == NULL)
755
* No matter what happens after this, we want to stop filtering.
756
* XXX If we handle nested contents, we only want to stop filtering
757
* if we are finishing off the *last* worker.
759
SEC_ASN1DecoderClearFilterProc (p7dcx->dcx);
762
* Handle the last block.
764
sec_pkcs7_decoder_work_data (p7dcx, worker, NULL, 0, PR_TRUE);
767
* All done, destroy it.
769
sec_PKCS7DestroyDecryptObject (worker->decryptobj);
770
worker->decryptobj = NULL;
777
sec_pkcs7_decoder_notify (void *arg, PRBool before, void *dest, int depth)
779
SEC_PKCS7DecoderContext *p7dcx;
780
SEC_PKCS7ContentInfo *cinfo;
781
SEC_PKCS7SignedData *sigd;
782
SEC_PKCS7EnvelopedData *envd;
783
SEC_PKCS7SignedAndEnvelopedData *saed;
784
SEC_PKCS7EncryptedData *encd;
785
SEC_PKCS7DigestedData *digd;
790
* Just to make the code easier to read, create an "after" variable
791
* that is equivalent to "not before".
792
* (This used to be just the statement "after = !before", but that
793
* causes a warning on the mac; to avoid that, we do it the long way.)
800
p7dcx = (SEC_PKCS7DecoderContext*)arg;
801
cinfo = p7dcx->cinfo;
803
if (cinfo->contentTypeTag == NULL) {
804
if (after && dest == &(cinfo->contentType))
805
cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType));
809
switch (cinfo->contentTypeTag->offset) {
810
case SEC_OID_PKCS7_SIGNED_DATA:
811
sigd = cinfo->content.signedData;
815
if (sigd->contentInfo.contentTypeTag == NULL) {
816
if (after && dest == &(sigd->contentInfo.contentType))
817
sigd->contentInfo.contentTypeTag =
818
SECOID_FindOID(&(sigd->contentInfo.contentType));
823
* We only set up a filtering digest if the content is
824
* plain DATA; anything else needs more work because a
825
* second pass is required to produce a DER encoding from
826
* an input that can be BER encoded. (This is a requirement
827
* of PKCS7 that is unfortunate, but there you have it.)
829
* XXX Also, since we stop here if this is not DATA, the
830
* inner content is not getting processed at all. Someday
831
* we may want to fix that.
833
if (sigd->contentInfo.contentTypeTag->offset != SEC_OID_PKCS7_DATA) {
834
/* XXX Set an error in p7dcx->error */
835
SEC_ASN1DecoderClearNotifyProc (p7dcx->dcx);
840
* Just before the content, we want to set up a digest context
841
* for each digest algorithm listed, and start a filter which
842
* will run all of the contents bytes through that digest.
844
if (before && dest == &(sigd->contentInfo.content)) {
845
rv = sec_pkcs7_decoder_start_digests (p7dcx, depth,
846
sigd->digestAlgorithms);
847
if (rv != SECSuccess)
848
SEC_ASN1DecoderClearNotifyProc (p7dcx->dcx);
854
* XXX To handle nested types, here is where we would want
855
* to check for inner boundaries that need handling.
861
if (after && dest == &(sigd->contentInfo.content)) {
863
* Close out the digest contexts. We ignore any error
864
* because we are stopping anyway; the error status left
865
* behind in p7dcx will be seen by outer functions.
867
(void) sec_pkcs7_decoder_finish_digests (p7dcx, cinfo->poolp,
871
* XXX To handle nested contents, we would need to remove
872
* the worker from the chain (and free it).
878
SEC_ASN1DecoderClearNotifyProc (p7dcx->dcx);
882
case SEC_OID_PKCS7_ENVELOPED_DATA:
883
envd = cinfo->content.envelopedData;
887
if (envd->encContentInfo.contentTypeTag == NULL) {
888
if (after && dest == &(envd->encContentInfo.contentType))
889
envd->encContentInfo.contentTypeTag =
890
SECOID_FindOID(&(envd->encContentInfo.contentType));
895
* Just before the content, we want to set up a decryption
896
* context, and start a filter which will run all of the
897
* contents bytes through it to determine the plain content.
899
if (before && dest == &(envd->encContentInfo.encContent)) {
900
rv = sec_pkcs7_decoder_start_decrypt (p7dcx, depth,
901
envd->recipientInfos,
902
&(envd->encContentInfo),
904
if (rv != SECSuccess)
905
SEC_ASN1DecoderClearNotifyProc (p7dcx->dcx);
913
if (after && dest == &(envd->encContentInfo.encContent)) {
915
* Close out the decryption context. We ignore any error
916
* because we are stopping anyway; the error status left
917
* behind in p7dcx will be seen by outer functions.
919
(void) sec_pkcs7_decoder_finish_decrypt (p7dcx, cinfo->poolp,
920
&(envd->encContentInfo));
923
* XXX To handle nested contents, we would need to remove
924
* the worker from the chain (and free it).
930
SEC_ASN1DecoderClearNotifyProc (p7dcx->dcx);
934
case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
935
saed = cinfo->content.signedAndEnvelopedData;
939
if (saed->encContentInfo.contentTypeTag == NULL) {
940
if (after && dest == &(saed->encContentInfo.contentType))
941
saed->encContentInfo.contentTypeTag =
942
SECOID_FindOID(&(saed->encContentInfo.contentType));
947
* Just before the content, we want to set up a decryption
948
* context *and* digest contexts, and start a filter which
949
* will run all of the contents bytes through both.
951
if (before && dest == &(saed->encContentInfo.encContent)) {
952
rv = sec_pkcs7_decoder_start_decrypt (p7dcx, depth,
953
saed->recipientInfos,
954
&(saed->encContentInfo),
956
if (rv == SECSuccess)
957
rv = sec_pkcs7_decoder_start_digests (p7dcx, depth,
958
saed->digestAlgorithms);
959
if (rv != SECSuccess)
960
SEC_ASN1DecoderClearNotifyProc (p7dcx->dcx);
968
if (after && dest == &(saed->encContentInfo.encContent)) {
970
* Close out the decryption and digests contexts.
971
* We ignore any errors because we are stopping anyway;
972
* the error status left behind in p7dcx will be seen by
975
* Note that the decrypt stuff must be called first;
976
* it may have a last buffer to do which in turn has
977
* to be added to the digest.
979
(void) sec_pkcs7_decoder_finish_decrypt (p7dcx, cinfo->poolp,
980
&(saed->encContentInfo));
981
(void) sec_pkcs7_decoder_finish_digests (p7dcx, cinfo->poolp,
985
* XXX To handle nested contents, we would need to remove
986
* the worker from the chain (and free it).
992
SEC_ASN1DecoderClearNotifyProc (p7dcx->dcx);
996
case SEC_OID_PKCS7_DIGESTED_DATA:
997
digd = cinfo->content.digestedData;
1000
* XXX Want to do the digest or not? Maybe future enhancement...
1002
if (before && dest == &(digd->contentInfo.content.data)) {
1003
SEC_ASN1DecoderSetFilterProc (p7dcx->dcx, sec_pkcs7_decoder_filter,
1005
(PRBool)(p7dcx->cb != NULL));
1012
if (after && dest == &(digd->contentInfo.content.data)) {
1013
SEC_ASN1DecoderClearFilterProc (p7dcx->dcx);
1017
case SEC_OID_PKCS7_ENCRYPTED_DATA:
1018
encd = cinfo->content.encryptedData;
1021
* XXX If the decryption key callback is set, we want to start
1022
* the decryption. If the callback is not set, we will treat the
1023
* content as plain data, since we do not have the key.
1025
* Is this the proper thing to do?
1027
if (before && dest == &(encd->encContentInfo.encContent)) {
1029
* Start the encryption process if the decryption key callback
1030
* is present. Otherwise, treat the content like plain data.
1033
if (p7dcx->dkcb != NULL) {
1034
rv = sec_pkcs7_decoder_start_decrypt (p7dcx, depth, NULL,
1035
&(encd->encContentInfo),
1039
if (rv != SECSuccess)
1040
SEC_ASN1DecoderClearNotifyProc (p7dcx->dcx);
1048
if (after && dest == &(encd->encContentInfo.encContent)) {
1050
* Close out the decryption context. We ignore any error
1051
* because we are stopping anyway; the error status left
1052
* behind in p7dcx will be seen by outer functions.
1054
(void) sec_pkcs7_decoder_finish_decrypt (p7dcx, cinfo->poolp,
1055
&(encd->encContentInfo));
1060
SEC_ASN1DecoderClearNotifyProc (p7dcx->dcx);
1064
case SEC_OID_PKCS7_DATA:
1066
* If a output callback has been specified, we want to set the filter
1067
* to call the callback. This is taken care of in
1068
* sec_pkcs7_decoder_start_decrypt() or
1069
* sec_pkcs7_decoder_start_digests() for the other content types.
1072
if (before && dest == &(cinfo->content.data)) {
1075
* Set the filter proc up.
1077
SEC_ASN1DecoderSetFilterProc (p7dcx->dcx,
1078
sec_pkcs7_decoder_filter,
1080
(PRBool)(p7dcx->cb != NULL));
1084
if (after && dest == &(cinfo->content.data)) {
1086
* Time to clean up after ourself, stop the Notify and Filter
1089
SEC_ASN1DecoderClearNotifyProc (p7dcx->dcx);
1090
SEC_ASN1DecoderClearFilterProc (p7dcx->dcx);
1095
SEC_ASN1DecoderClearNotifyProc (p7dcx->dcx);
1101
SEC_PKCS7DecoderContext *
1102
SEC_PKCS7DecoderStart(SEC_PKCS7DecoderContentCallback cb, void *cb_arg,
1103
SECKEYGetPasswordKey pwfn, void *pwfn_arg,
1104
SEC_PKCS7GetDecryptKeyCallback decrypt_key_cb,
1105
void *decrypt_key_cb_arg,
1106
SEC_PKCS7DecryptionAllowedCallback decrypt_allowed_cb)
1108
SEC_PKCS7DecoderContext *p7dcx;
1109
SEC_ASN1DecoderContext *dcx;
1110
SEC_PKCS7ContentInfo *cinfo;
1113
poolp = PORT_NewArena (1024); /* XXX what is right value? */
1117
cinfo = (SEC_PKCS7ContentInfo*)PORT_ArenaZAlloc (poolp, sizeof(*cinfo));
1118
if (cinfo == NULL) {
1119
PORT_FreeArena (poolp, PR_FALSE);
1123
cinfo->poolp = poolp;
1125
cinfo->pwfn_arg = pwfn_arg;
1126
cinfo->created = PR_FALSE;
1127
cinfo->refCount = 1;
1130
(SEC_PKCS7DecoderContext*)PORT_ZAlloc (sizeof(SEC_PKCS7DecoderContext));
1131
if (p7dcx == NULL) {
1132
PORT_FreeArena (poolp, PR_FALSE);
1136
p7dcx->tmp_poolp = PORT_NewArena (1024); /* XXX what is right value? */
1137
if (p7dcx->tmp_poolp == NULL) {
1139
PORT_FreeArena (poolp, PR_FALSE);
1143
dcx = SEC_ASN1DecoderStart (poolp, cinfo, sec_PKCS7ContentInfoTemplate);
1145
PORT_FreeArena (p7dcx->tmp_poolp, PR_FALSE);
1147
PORT_FreeArena (poolp, PR_FALSE);
1151
SEC_ASN1DecoderSetNotifyProc (dcx, sec_pkcs7_decoder_notify, p7dcx);
1154
p7dcx->cinfo = cinfo;
1156
p7dcx->cb_arg = cb_arg;
1158
p7dcx->pwfn_arg = pwfn_arg;
1159
p7dcx->dkcb = decrypt_key_cb;
1160
p7dcx->dkcb_arg = decrypt_key_cb_arg;
1161
p7dcx->decrypt_allowed_cb = decrypt_allowed_cb;
1168
* Do the next chunk of PKCS7 decoding. If there is a problem, set
1169
* an error and return a failure status. Note that in the case of
1170
* an error, this routine is still prepared to be called again and
1171
* again in case that is the easiest route for our caller to take.
1172
* We simply detect it and do not do anything except keep setting
1173
* that error in case our caller has not noticed it yet...
1176
SEC_PKCS7DecoderUpdate(SEC_PKCS7DecoderContext *p7dcx,
1177
const char *buf, unsigned long len)
1179
if (p7dcx->cinfo != NULL && p7dcx->dcx != NULL) {
1180
PORT_Assert (p7dcx->error == 0);
1181
if (p7dcx->error == 0) {
1182
if (SEC_ASN1DecoderUpdate (p7dcx->dcx, buf, len) != SECSuccess) {
1183
p7dcx->error = PORT_GetError();
1184
PORT_Assert (p7dcx->error);
1185
if (p7dcx->error == 0)
1192
if (p7dcx->dcx != NULL) {
1193
(void) SEC_ASN1DecoderFinish (p7dcx->dcx);
1196
if (p7dcx->cinfo != NULL) {
1197
SEC_PKCS7DestroyContentInfo (p7dcx->cinfo);
1198
p7dcx->cinfo = NULL;
1200
PORT_SetError (p7dcx->error);
1208
SEC_PKCS7ContentInfo *
1209
SEC_PKCS7DecoderFinish(SEC_PKCS7DecoderContext *p7dcx)
1211
SEC_PKCS7ContentInfo *cinfo;
1213
cinfo = p7dcx->cinfo;
1214
if (p7dcx->dcx != NULL) {
1215
if (SEC_ASN1DecoderFinish (p7dcx->dcx) != SECSuccess) {
1216
SEC_PKCS7DestroyContentInfo (cinfo);
1220
/* free any NSS data structures */
1221
if (p7dcx->worker.decryptobj) {
1222
sec_PKCS7DestroyDecryptObject (p7dcx->worker.decryptobj);
1224
PORT_FreeArena (p7dcx->tmp_poolp, PR_FALSE);
1230
SEC_PKCS7ContentInfo *
1231
SEC_PKCS7DecodeItem(SECItem *p7item,
1232
SEC_PKCS7DecoderContentCallback cb, void *cb_arg,
1233
SECKEYGetPasswordKey pwfn, void *pwfn_arg,
1234
SEC_PKCS7GetDecryptKeyCallback decrypt_key_cb,
1235
void *decrypt_key_cb_arg,
1236
SEC_PKCS7DecryptionAllowedCallback decrypt_allowed_cb)
1238
SEC_PKCS7DecoderContext *p7dcx;
1240
p7dcx = SEC_PKCS7DecoderStart(cb, cb_arg, pwfn, pwfn_arg, decrypt_key_cb,
1241
decrypt_key_cb_arg, decrypt_allowed_cb);
1242
(void) SEC_PKCS7DecoderUpdate(p7dcx, (char *) p7item->data, p7item->len);
1243
return SEC_PKCS7DecoderFinish(p7dcx);
1247
* Abort the ASN.1 stream. Used by pkcs 12
1250
SEC_PKCS7DecoderAbort(SEC_PKCS7DecoderContext *p7dcx, int error)
1253
SEC_ASN1DecoderAbort(p7dcx->dcx, error);
1258
* If the thing contains any certs or crls return true; false otherwise.
1261
SEC_PKCS7ContainsCertsOrCrls(SEC_PKCS7ContentInfo *cinfo)
1265
CERTSignedCrl **crls;
1267
kind = SEC_PKCS7ContentType (cinfo);
1270
case SEC_OID_PKCS7_DATA:
1271
case SEC_OID_PKCS7_DIGESTED_DATA:
1272
case SEC_OID_PKCS7_ENVELOPED_DATA:
1273
case SEC_OID_PKCS7_ENCRYPTED_DATA:
1275
case SEC_OID_PKCS7_SIGNED_DATA:
1276
certs = cinfo->content.signedData->rawCerts;
1277
crls = cinfo->content.signedData->crls;
1279
case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
1280
certs = cinfo->content.signedAndEnvelopedData->rawCerts;
1281
crls = cinfo->content.signedAndEnvelopedData->crls;
1286
* I know this could be collapsed, but I was in a mood to be explicit.
1288
if (certs != NULL && certs[0] != NULL)
1290
else if (crls != NULL && crls[0] != NULL)
1296
/* return the content length...could use GetContent, however we
1297
* need the encrypted content length
1300
SEC_PKCS7IsContentEmpty(SEC_PKCS7ContentInfo *cinfo, unsigned int minLen)
1302
SECItem *item = NULL;
1308
switch(SEC_PKCS7ContentType(cinfo))
1310
case SEC_OID_PKCS7_DATA:
1311
item = cinfo->content.data;
1313
case SEC_OID_PKCS7_ENCRYPTED_DATA:
1314
item = &cinfo->content.encryptedData->encContentInfo.encContent;
1317
/* add other types */
1323
} else if(item->len <= minLen) {
1332
SEC_PKCS7ContentIsEncrypted(SEC_PKCS7ContentInfo *cinfo)
1336
kind = SEC_PKCS7ContentType (cinfo);
1339
case SEC_OID_PKCS7_DATA:
1340
case SEC_OID_PKCS7_DIGESTED_DATA:
1341
case SEC_OID_PKCS7_SIGNED_DATA:
1343
case SEC_OID_PKCS7_ENCRYPTED_DATA:
1344
case SEC_OID_PKCS7_ENVELOPED_DATA:
1345
case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
1352
* If the PKCS7 content has a signature (not just *could* have a signature)
1353
* return true; false otherwise. This can/should be called before calling
1354
* VerifySignature, which will always indicate failure if no signature is
1355
* present, but that does not mean there even was a signature!
1356
* Note that the content itself can be empty (detached content was sent
1357
* another way); it is the presence of the signature that matters.
1360
SEC_PKCS7ContentIsSigned(SEC_PKCS7ContentInfo *cinfo)
1363
SEC_PKCS7SignerInfo **signerinfos;
1365
kind = SEC_PKCS7ContentType (cinfo);
1368
case SEC_OID_PKCS7_DATA:
1369
case SEC_OID_PKCS7_DIGESTED_DATA:
1370
case SEC_OID_PKCS7_ENVELOPED_DATA:
1371
case SEC_OID_PKCS7_ENCRYPTED_DATA:
1373
case SEC_OID_PKCS7_SIGNED_DATA:
1374
signerinfos = cinfo->content.signedData->signerInfos;
1376
case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
1377
signerinfos = cinfo->content.signedAndEnvelopedData->signerInfos;
1382
* I know this could be collapsed; but I kind of think it will get
1383
* more complicated before I am finished, so...
1385
if (signerinfos != NULL && signerinfos[0] != NULL)
1393
* SEC_PKCS7ContentVerifySignature
1394
* Look at a PKCS7 contentInfo and check if the signature is good.
1395
* The digest was either calculated earlier (and is stored in the
1396
* contentInfo itself) or is passed in via "detached_digest".
1398
* The verification checks that the signing cert is valid and trusted
1399
* for the purpose specified by "certusage".
1401
* In addition, if "keepcerts" is true, add any new certificates found
1402
* into our local database.
1404
* XXX Each place which returns PR_FALSE should be sure to have a good
1405
* error set for inspection by the caller. Alternatively, we could create
1406
* an enumeration of success and each type of failure and return that
1407
* instead of a boolean. For now, the default in a bad situation is to
1408
* set the error to SEC_ERROR_PKCS7_BAD_SIGNATURE. But this should be
1409
* reviewed; better (more specific) errors should be possible (to distinguish
1410
* a signature failure from a badly-formed pkcs7 signedData, for example).
1411
* Some of the errors should probably just be SEC_ERROR_BAD_SIGNATURE,
1412
* but that has a less helpful error string associated with it right now;
1413
* if/when that changes, review and change these as needed.
1415
* XXX This is broken wrt signedAndEnvelopedData. In that case, the
1416
* message digest is doubly encrypted -- first encrypted with the signer
1417
* private key but then again encrypted with the bulk encryption key used
1418
* to encrypt the content. So before we can pass the digest to VerifyDigest,
1419
* we need to decrypt it with the bulk encryption key. Also, in this case,
1420
* there should be NO authenticatedAttributes (signerinfo->authAttr should
1424
sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo,
1425
SECCertUsage certusage,
1426
SECItem *detached_digest,
1427
HASH_HashType digest_type,
1430
SECAlgorithmID **digestalgs, *bulkid;
1434
CERTSignedCrl **crls;
1435
SEC_PKCS7SignerInfo **signerinfos, *signerinfo;
1436
CERTCertificate *cert, **certs;
1438
CERTCertDBHandle *certdb, *defaultdb;
1439
SECOidData *algiddata;
1441
SECKEYPublicKey *publickey;
1442
SECItem *content_type;
1444
SECItem *encoded_stime;
1449
* Everything needed in order to "goto done" safely.
1456
defaultdb = CERT_GetDefaultCertDB();
1459
if (! SEC_PKCS7ContentIsSigned(cinfo)) {
1460
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
1464
PORT_Assert (cinfo->contentTypeTag != NULL);
1466
switch (cinfo->contentTypeTag->offset) {
1468
case SEC_OID_PKCS7_DATA:
1469
case SEC_OID_PKCS7_DIGESTED_DATA:
1470
case SEC_OID_PKCS7_ENVELOPED_DATA:
1471
case SEC_OID_PKCS7_ENCRYPTED_DATA:
1472
/* Could only get here if SEC_PKCS7ContentIsSigned is broken. */
1474
case SEC_OID_PKCS7_SIGNED_DATA:
1476
SEC_PKCS7SignedData *sdp;
1478
sdp = cinfo->content.signedData;
1479
digestalgs = sdp->digestAlgorithms;
1480
digests = sdp->digests;
1481
rawcerts = sdp->rawCerts;
1483
signerinfos = sdp->signerInfos;
1484
content_type = &(sdp->contentInfo.contentType);
1489
case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
1491
SEC_PKCS7SignedAndEnvelopedData *saedp;
1493
saedp = cinfo->content.signedAndEnvelopedData;
1494
digestalgs = saedp->digestAlgorithms;
1495
digests = saedp->digests;
1496
rawcerts = saedp->rawCerts;
1498
signerinfos = saedp->signerInfos;
1499
content_type = &(saedp->encContentInfo.contentType);
1500
sigkey = saedp->sigKey;
1501
bulkid = &(saedp->encContentInfo.contentEncAlg);
1506
if ((signerinfos == NULL) || (signerinfos[0] == NULL)) {
1507
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
1512
* XXX Need to handle multiple signatures; checking them is easy,
1513
* but what should be the semantics here (like, return value)?
1515
if (signerinfos[1] != NULL) {
1516
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
1520
signerinfo = signerinfos[0];
1523
* XXX I would like to just pass the issuerAndSN, along with the rawcerts
1524
* and crls, to some function that did all of this certificate stuff
1525
* (open/close the database if necessary, verifying the certs, etc.)
1526
* and gave me back a cert pointer if all was good.
1529
if (certdb == NULL) {
1534
if (rawcerts != NULL) {
1535
for (; rawcerts[certcount] != NULL; certcount++) {
1541
* Note that the result of this is that each cert in "certs"
1542
* needs to be destroyed.
1544
rv = CERT_ImportCerts(certdb, certusage, certcount, rawcerts, &certs,
1545
keepcerts, PR_FALSE, NULL);
1546
if ( rv != SECSuccess ) {
1551
* This cert will also need to be freed, but since we save it
1552
* in signerinfo for later, we do not want to destroy it when
1553
* we leave this function -- we let the clean-up of the entire
1554
* cinfo structure later do the destroy of this cert.
1556
cert = CERT_FindCertByIssuerAndSN(certdb, signerinfo->issuerAndSN);
1561
signerinfo->cert = cert;
1564
* Get and convert the signing time; if available, it will be used
1565
* both on the cert verification and for importing the sender
1568
encoded_stime = SEC_PKCS7GetSigningTime (cinfo);
1569
if (encoded_stime != NULL) {
1570
if (DER_DecodeTimeChoice (&stime, encoded_stime) != SECSuccess)
1571
encoded_stime = NULL; /* conversion failed, so pretend none */
1575
* XXX This uses the signing time, if available. Additionally, we
1576
* might want to, if there is no signing time, get the message time
1577
* from the mail header itself, and use that. That would require
1578
* a change to our interface though, and for S/MIME callers to pass
1579
* in a time (and for non-S/MIME callers to pass in nothing, or
1580
* maybe make them pass in the current time, always?).
1582
if (CERT_VerifyCert (certdb, cert, PR_TRUE, certusage,
1583
encoded_stime != NULL ? stime : PR_Now(),
1584
cinfo->pwfn_arg, NULL) != SECSuccess)
1587
* XXX Give the user an option to check the signature anyway?
1588
* If we want to do this, need to give a way to leave and display
1589
* some dialog and get the answer and come back through (or do
1590
* the rest of what we do below elsewhere, maybe by putting it
1591
* in a function that we call below and could call from a dialog
1597
publickey = CERT_ExtractPublicKey (cert);
1598
if (publickey == NULL)
1602
* XXX No! If digests is empty, see if we can create it now by
1603
* digesting the contents. This is necessary if we want to allow
1604
* somebody to do a simple decode (without filtering, etc.) and
1605
* then later call us here to do the verification.
1606
* OR, we can just specify that the interface to this routine
1607
* *requires* that the digest(s) be done before calling and either
1608
* stashed in the struct itself or passed in explicitly (as would
1609
* be done for detached contents).
1611
if ((digests == NULL || digests[0] == NULL)
1612
&& (detached_digest == NULL || detached_digest->data == NULL))
1616
* Find and confirm digest algorithm.
1618
algiddata = SECOID_FindOID (&(signerinfo->digestAlg.algorithm));
1620
if (detached_digest != NULL) {
1621
HASH_HashType found_type = HASH_GetHashTypeByOidTag(algiddata->offset);
1622
unsigned int hashLen = HASH_ResultLen(digest_type);
1624
if (digest_type != found_type ||
1625
digest_type == HASH_AlgNULL ||
1626
detached_digest->len != hashLen) {
1627
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
1630
digest = detached_digest;
1632
PORT_Assert (digestalgs != NULL && digestalgs[0] != NULL);
1633
if (digestalgs == NULL || digestalgs[0] == NULL) {
1634
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
1639
* pick digest matching signerinfo->digestAlg from digests
1641
if (algiddata == NULL) {
1642
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
1645
for (i = 0; digestalgs[i] != NULL; i++) {
1646
if (SECOID_FindOID (&(digestalgs[i]->algorithm)) == algiddata)
1649
if (digestalgs[i] == NULL) {
1650
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
1654
digest = digests[i];
1658
* XXX This may not be the right set of algorithms to check.
1659
* I'd prefer to trust that just calling VFY_Verify{Data,Digest}
1660
* would do the right thing (and set an error if it could not);
1661
* then additional algorithms could be handled by that code
1662
* and we would Just Work. So this check should just be removed,
1663
* but not until the VFY code is better at setting errors.
1665
algiddata = SECOID_FindOID (&(signerinfo->digestEncAlg.algorithm));
1666
if (algiddata == NULL ||
1667
((algiddata->offset != SEC_OID_PKCS1_RSA_ENCRYPTION) &&
1668
#ifdef NSS_ECC_MORE_THAN_SUITE_B
1669
(algiddata->offset != SEC_OID_ANSIX962_EC_PUBLIC_KEY) &&
1671
(algiddata->offset != SEC_OID_ANSIX9_DSA_SIGNATURE))) {
1672
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
1676
if (signerinfo->authAttr != NULL) {
1677
SEC_PKCS7Attribute *attr;
1679
SECItem encoded_attrs;
1682
* We have a sigkey only for signedAndEnvelopedData, which is
1683
* not supposed to have any authenticated attributes.
1685
if (sigkey != NULL) {
1686
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
1691
* PKCS #7 says that if there are any authenticated attributes,
1692
* then there must be one for content type which matches the
1693
* content type of the content being signed, and there must
1694
* be one for message digest which matches our message digest.
1695
* So check these things first.
1696
* XXX Might be nice to have a compare-attribute-value function
1697
* which could collapse the following nicely.
1699
attr = sec_PKCS7FindAttribute (signerinfo->authAttr,
1700
SEC_OID_PKCS9_CONTENT_TYPE, PR_TRUE);
1701
value = sec_PKCS7AttributeValue (attr);
1702
if (value == NULL || value->len != content_type->len) {
1703
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
1706
if (PORT_Memcmp (value->data, content_type->data, value->len) != 0) {
1707
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
1711
attr = sec_PKCS7FindAttribute (signerinfo->authAttr,
1712
SEC_OID_PKCS9_MESSAGE_DIGEST, PR_TRUE);
1713
value = sec_PKCS7AttributeValue (attr);
1714
if (value == NULL || value->len != digest->len) {
1715
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
1718
if (PORT_Memcmp (value->data, digest->data, value->len) != 0) {
1719
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
1724
* Okay, we met the constraints of the basic attributes.
1725
* Now check the signature, which is based on a digest of
1726
* the DER-encoded authenticated attributes. So, first we
1727
* encode and then we digest/verify.
1729
encoded_attrs.data = NULL;
1730
encoded_attrs.len = 0;
1731
if (sec_PKCS7EncodeAttributes (NULL, &encoded_attrs,
1732
&(signerinfo->authAttr)) == NULL)
1735
if (encoded_attrs.data == NULL || encoded_attrs.len == 0) {
1736
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
1741
* XXX the 5th (algid) argument should be the signature algorithm.
1742
* See sec_pkcs7_pick_sign_alg in p7encode.c.
1744
goodsig = (PRBool)(VFY_VerifyData (encoded_attrs.data,
1746
publickey, &(signerinfo->encDigest),
1747
SECOID_GetAlgorithmTag(&(signerinfo->digestEncAlg)),
1748
cinfo->pwfn_arg) == SECSuccess);
1749
PORT_Free (encoded_attrs.data);
1756
* No authenticated attributes.
1757
* The signature is based on the plain message digest.
1760
sig = &(signerinfo->encDigest);
1761
if (sig->len == 0) { /* bad signature */
1762
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
1766
if (sigkey != NULL) {
1767
sec_PKCS7CipherObject *decryptobj;
1768
unsigned int buflen;
1771
* For signedAndEnvelopedData, we first must decrypt the encrypted
1772
* digest with the bulk encryption key. The result is the normal
1773
* encrypted digest (aka the signature).
1775
decryptobj = sec_PKCS7CreateDecryptObject (sigkey, bulkid);
1776
if (decryptobj == NULL)
1779
buflen = sec_PKCS7DecryptLength (decryptobj, sig->len, PR_TRUE);
1780
PORT_Assert (buflen);
1781
if (buflen == 0) { /* something is wrong */
1782
sec_PKCS7DestroyDecryptObject (decryptobj);
1786
holder.data = (unsigned char*)PORT_Alloc (buflen);
1787
if (holder.data == NULL) {
1788
sec_PKCS7DestroyDecryptObject (decryptobj);
1792
rv = sec_PKCS7Decrypt (decryptobj, holder.data, &holder.len, buflen,
1793
sig->data, sig->len, PR_TRUE);
1794
sec_PKCS7DestroyDecryptObject (decryptobj);
1795
if (rv != SECSuccess) {
1803
* XXX the 4th (algid) argument should be the signature algorithm.
1804
* See sec_pkcs7_pick_sign_alg in p7encode.c.
1806
goodsig = (PRBool)(VFY_VerifyDigest (digest, publickey, sig,
1807
SECOID_GetAlgorithmTag(&(signerinfo->digestEncAlg)),
1811
if (sigkey != NULL) {
1812
PORT_Assert (sig == &holder);
1813
PORT_ZFree (holder.data, holder.len);
1819
* XXX Change the generic error into our specific one, because
1820
* in that case we get a better explanation out of the Security
1821
* Advisor. This is really a bug in our error strings (the
1822
* "generic" error has a lousy/wrong message associated with it
1823
* which assumes the signature verification was done for the
1824
* purposes of checking the issuer signature on a certificate)
1825
* but this is at least an easy workaround and/or in the
1826
* Security Advisor, which specifically checks for the error
1827
* SEC_ERROR_PKCS7_BAD_SIGNATURE and gives more explanation
1828
* in that case but does not similarly check for
1829
* SEC_ERROR_BAD_SIGNATURE. It probably should, but then would
1830
* probably say the wrong thing in the case that it *was* the
1831
* certificate signature check that failed during the cert
1832
* verification done above. Our error handling is really a mess.
1834
if (PORT_GetError() == SEC_ERROR_BAD_SIGNATURE)
1835
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
1840
* Only save the smime profile if we are checking an email message and
1841
* the cert has an email address in it.
1843
if ( cert->emailAddr && cert->emailAddr[0] &&
1844
( ( certusage == certUsageEmailSigner ) ||
1845
( certusage == certUsageEmailRecipient ) ) ) {
1846
SECItem *profile = NULL;
1850
* Remember the current error set because we do not care about
1851
* anything set by the functions we are about to call.
1853
save_error = PORT_GetError();
1855
if (goodsig && (signerinfo->authAttr != NULL)) {
1857
* If the signature is good, then we can save the S/MIME profile,
1860
SEC_PKCS7Attribute *attr;
1862
attr = sec_PKCS7FindAttribute (signerinfo->authAttr,
1863
SEC_OID_PKCS9_SMIME_CAPABILITIES,
1865
profile = sec_PKCS7AttributeValue (attr);
1868
rv = CERT_SaveSMimeProfile (cert, profile, encoded_stime);
1871
* Restore the saved error in case the calls above set a new
1872
* one that we do not actually care about.
1874
PORT_SetError (save_error);
1877
* XXX Failure is not indicated anywhere -- the signature
1878
* verification itself is unaffected by whether or not the
1879
* profile was successfully saved.
1887
* See comment above about why we do not want to destroy cert
1892
CERT_DestroyCertArray (certs, certcount);
1894
if (publickey != NULL)
1895
SECKEY_DestroyPublicKey (publickey);
1901
* SEC_PKCS7VerifySignature
1902
* Look at a PKCS7 contentInfo and check if the signature is good.
1903
* The verification checks that the signing cert is valid and trusted
1904
* for the purpose specified by "certusage".
1906
* In addition, if "keepcerts" is true, add any new certificates found
1907
* into our local database.
1910
SEC_PKCS7VerifySignature(SEC_PKCS7ContentInfo *cinfo,
1911
SECCertUsage certusage,
1914
return sec_pkcs7_verify_signature (cinfo, certusage,
1915
NULL, HASH_AlgNULL, keepcerts);
1919
* SEC_PKCS7VerifyDetachedSignature
1920
* Look at a PKCS7 contentInfo and check if the signature matches
1921
* a passed-in digest (calculated, supposedly, from detached contents).
1922
* The verification checks that the signing cert is valid and trusted
1923
* for the purpose specified by "certusage".
1925
* In addition, if "keepcerts" is true, add any new certificates found
1926
* into our local database.
1929
SEC_PKCS7VerifyDetachedSignature(SEC_PKCS7ContentInfo *cinfo,
1930
SECCertUsage certusage,
1931
SECItem *detached_digest,
1932
HASH_HashType digest_type,
1935
return sec_pkcs7_verify_signature (cinfo, certusage,
1936
detached_digest, digest_type,
1942
* Return the asked-for portion of the name of the signer of a PKCS7
1945
* Returns a pointer to allocated memory, which must be freed.
1946
* A NULL return value is an error.
1949
#define sec_common_name 1
1950
#define sec_email_address 2
1953
sec_pkcs7_get_signer_cert_info(SEC_PKCS7ContentInfo *cinfo, int selector)
1956
SEC_PKCS7SignerInfo **signerinfos;
1957
CERTCertificate *signercert;
1960
kind = SEC_PKCS7ContentType (cinfo);
1963
case SEC_OID_PKCS7_DATA:
1964
case SEC_OID_PKCS7_DIGESTED_DATA:
1965
case SEC_OID_PKCS7_ENVELOPED_DATA:
1966
case SEC_OID_PKCS7_ENCRYPTED_DATA:
1969
case SEC_OID_PKCS7_SIGNED_DATA:
1971
SEC_PKCS7SignedData *sdp;
1973
sdp = cinfo->content.signedData;
1974
signerinfos = sdp->signerInfos;
1977
case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
1979
SEC_PKCS7SignedAndEnvelopedData *saedp;
1981
saedp = cinfo->content.signedAndEnvelopedData;
1982
signerinfos = saedp->signerInfos;
1987
if (signerinfos == NULL || signerinfos[0] == NULL)
1990
signercert = signerinfos[0]->cert;
1993
* No cert there; see if we can find one by calling verify ourselves.
1995
if (signercert == NULL) {
1997
* The cert usage does not matter in this case, because we do not
1998
* actually care about the verification itself, but we have to pick
1999
* some valid usage to pass in.
2001
(void) sec_pkcs7_verify_signature (cinfo, certUsageEmailSigner,
2002
NULL, HASH_AlgNULL, PR_FALSE);
2003
signercert = signerinfos[0]->cert;
2004
if (signercert == NULL)
2009
case sec_common_name:
2010
container = CERT_GetCommonName (&signercert->subject);
2012
case sec_email_address:
2013
if(signercert->emailAddr && signercert->emailAddr[0]) {
2014
container = PORT_Strdup(signercert->emailAddr);
2029
SEC_PKCS7GetSignerCommonName(SEC_PKCS7ContentInfo *cinfo)
2031
return sec_pkcs7_get_signer_cert_info(cinfo, sec_common_name);
2035
SEC_PKCS7GetSignerEmailAddress(SEC_PKCS7ContentInfo *cinfo)
2037
return sec_pkcs7_get_signer_cert_info(cinfo, sec_email_address);
2042
* Return the signing time, in UTCTime format, of a PKCS7 contentInfo.
2045
SEC_PKCS7GetSigningTime(SEC_PKCS7ContentInfo *cinfo)
2047
SEC_PKCS7SignerInfo **signerinfos;
2048
SEC_PKCS7Attribute *attr;
2050
if (SEC_PKCS7ContentType (cinfo) != SEC_OID_PKCS7_SIGNED_DATA)
2053
signerinfos = cinfo->content.signedData->signerInfos;
2056
* No signature, or more than one, means no deal.
2058
if (signerinfos == NULL || signerinfos[0] == NULL || signerinfos[1] != NULL)
2061
attr = sec_PKCS7FindAttribute (signerinfos[0]->authAttr,
2062
SEC_OID_PKCS9_SIGNING_TIME, PR_TRUE);
2063
return sec_PKCS7AttributeValue (attr);