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  * CMS digestedData methods.
7  */
8 
9 #include "cmslocal.h"
10 
11 #include "secitem.h"
12 #include "secasn1.h"
13 #include "secoid.h"
14 #include "secerr.h"
15 
16 /*
17  * NSS_CMSDigestedData_Create - create a digestedData object (presumably for encoding)
18  *
19  * version will be set by NSS_CMSDigestedData_Encode_BeforeStart
20  * digestAlg is passed as parameter
21  * contentInfo must be filled by the user
22  * digest will be calculated while encoding
23  */
24 NSSCMSDigestedData *
NSS_CMSDigestedData_Create(NSSCMSMessage * cmsg,SECAlgorithmID * digestalg)25 NSS_CMSDigestedData_Create(NSSCMSMessage *cmsg, SECAlgorithmID *digestalg)
26 {
27     void *mark;
28     NSSCMSDigestedData *digd;
29     PLArenaPool *poolp;
30 
31     poolp = cmsg->poolp;
32 
33     mark = PORT_ArenaMark(poolp);
34 
35     digd = (NSSCMSDigestedData *)PORT_ArenaZAlloc(poolp, sizeof(NSSCMSDigestedData));
36     if (digd == NULL)
37         goto loser;
38 
39     digd->cmsg = cmsg;
40 
41     if (SECOID_CopyAlgorithmID(poolp, &(digd->digestAlg), digestalg) != SECSuccess)
42         goto loser;
43 
44     PORT_ArenaUnmark(poolp, mark);
45     return digd;
46 
47 loser:
48     PORT_ArenaRelease(poolp, mark);
49     return NULL;
50 }
51 
52 /*
53  * NSS_CMSDigestedData_Destroy - destroy a digestedData object
54  */
55 void
NSS_CMSDigestedData_Destroy(NSSCMSDigestedData * digd)56 NSS_CMSDigestedData_Destroy(NSSCMSDigestedData *digd)
57 {
58     /* everything's in a pool, so don't worry about the storage */
59     NSS_CMSContentInfo_Destroy(&(digd->contentInfo));
60     return;
61 }
62 
63 /*
64  * NSS_CMSDigestedData_GetContentInfo - return pointer to digestedData object's contentInfo
65  */
66 NSSCMSContentInfo *
NSS_CMSDigestedData_GetContentInfo(NSSCMSDigestedData * digd)67 NSS_CMSDigestedData_GetContentInfo(NSSCMSDigestedData *digd)
68 {
69     return &(digd->contentInfo);
70 }
71 
72 /*
73  * NSS_CMSDigestedData_Encode_BeforeStart - do all the necessary things to a DigestedData
74  *     before encoding begins.
75  *
76  * In particular:
77  *  - set the right version number. The contentInfo's content type must be set up already.
78  */
79 SECStatus
NSS_CMSDigestedData_Encode_BeforeStart(NSSCMSDigestedData * digd)80 NSS_CMSDigestedData_Encode_BeforeStart(NSSCMSDigestedData *digd)
81 {
82     unsigned long version;
83     SECItem *dummy;
84 
85     version = NSS_CMS_DIGESTED_DATA_VERSION_DATA;
86     if (!NSS_CMSType_IsData(NSS_CMSContentInfo_GetContentTypeTag(
87             &(digd->contentInfo))))
88         version = NSS_CMS_DIGESTED_DATA_VERSION_ENCAP;
89 
90     dummy = SEC_ASN1EncodeInteger(digd->cmsg->poolp, &(digd->version), version);
91     return (dummy == NULL) ? SECFailure : SECSuccess;
92 }
93 
94 /*
95  * NSS_CMSDigestedData_Encode_BeforeData - do all the necessary things to a DigestedData
96  *     before the encapsulated data is passed through the encoder.
97  *
98  * In detail:
99  *  - set up the digests if necessary
100  */
101 SECStatus
NSS_CMSDigestedData_Encode_BeforeData(NSSCMSDigestedData * digd)102 NSS_CMSDigestedData_Encode_BeforeData(NSSCMSDigestedData *digd)
103 {
104     SECStatus rv = NSS_CMSContentInfo_Private_Init(&digd->contentInfo);
105     if (rv != SECSuccess) {
106         return SECFailure;
107     }
108 
109     /* set up the digests */
110     if (digd->digestAlg.algorithm.len != 0 && digd->digest.len == 0) {
111         /* if digest is already there, do nothing */
112         digd->contentInfo.privateInfo->digcx = NSS_CMSDigestContext_StartSingle(&(digd->digestAlg));
113         if (digd->contentInfo.privateInfo->digcx == NULL)
114             return SECFailure;
115     }
116     return SECSuccess;
117 }
118 
119 /*
120  * NSS_CMSDigestedData_Encode_AfterData - do all the necessary things to a DigestedData
121  *     after all the encapsulated data was passed through the encoder.
122  *
123  * In detail:
124  *  - finish the digests
125  */
126 SECStatus
NSS_CMSDigestedData_Encode_AfterData(NSSCMSDigestedData * digd)127 NSS_CMSDigestedData_Encode_AfterData(NSSCMSDigestedData *digd)
128 {
129     SECStatus rv = SECSuccess;
130     /* did we have digest calculation going on? */
131     if (digd->contentInfo.privateInfo && digd->contentInfo.privateInfo->digcx) {
132         rv = NSS_CMSDigestContext_FinishSingle(digd->contentInfo.privateInfo->digcx,
133                                                digd->cmsg->poolp,
134                                                &(digd->digest));
135         /* error has been set by NSS_CMSDigestContext_FinishSingle */
136         digd->contentInfo.privateInfo->digcx = NULL;
137     }
138 
139     return rv;
140 }
141 
142 /*
143  * NSS_CMSDigestedData_Decode_BeforeData - do all the necessary things to a DigestedData
144  *     before the encapsulated data is passed through the encoder.
145  *
146  * In detail:
147  *  - set up the digests if necessary
148  */
149 SECStatus
NSS_CMSDigestedData_Decode_BeforeData(NSSCMSDigestedData * digd)150 NSS_CMSDigestedData_Decode_BeforeData(NSSCMSDigestedData *digd)
151 {
152     SECStatus rv;
153 
154     /* is there a digest algorithm yet? */
155     if (digd->digestAlg.algorithm.len == 0)
156         return SECFailure;
157 
158     rv = NSS_CMSContentInfo_Private_Init(&digd->contentInfo);
159     if (rv != SECSuccess) {
160         return SECFailure;
161     }
162 
163     digd->contentInfo.privateInfo->digcx = NSS_CMSDigestContext_StartSingle(&(digd->digestAlg));
164     if (digd->contentInfo.privateInfo->digcx == NULL)
165         return SECFailure;
166 
167     return SECSuccess;
168 }
169 
170 /*
171  * NSS_CMSDigestedData_Decode_AfterData - do all the necessary things to a DigestedData
172  *     after all the encapsulated data was passed through the encoder.
173  *
174  * In detail:
175  *  - finish the digests
176  */
177 SECStatus
NSS_CMSDigestedData_Decode_AfterData(NSSCMSDigestedData * digd)178 NSS_CMSDigestedData_Decode_AfterData(NSSCMSDigestedData *digd)
179 {
180     SECStatus rv = SECSuccess;
181     /* did we have digest calculation going on? */
182     if (digd->contentInfo.privateInfo && digd->contentInfo.privateInfo->digcx) {
183         rv = NSS_CMSDigestContext_FinishSingle(digd->contentInfo.privateInfo->digcx,
184                                                digd->cmsg->poolp,
185                                                &(digd->cdigest));
186         /* error has been set by NSS_CMSDigestContext_FinishSingle */
187         digd->contentInfo.privateInfo->digcx = NULL;
188     }
189 
190     return rv;
191 }
192 
193 /*
194  * NSS_CMSDigestedData_Decode_AfterEnd - finalize a digestedData.
195  *
196  * In detail:
197  *  - check the digests for equality
198  */
199 SECStatus
NSS_CMSDigestedData_Decode_AfterEnd(NSSCMSDigestedData * digd)200 NSS_CMSDigestedData_Decode_AfterEnd(NSSCMSDigestedData *digd)
201 {
202     /* did we have digest calculation going on? */
203     if (digd->cdigest.len != 0) {
204         /* XXX comparision btw digest & cdigest */
205         /* XXX set status */
206         /* TODO!!!! */
207     }
208 
209     return SECSuccess;
210 }
211