1/*
2 * The contents of this file are subject to the Mozilla Public
3 * License Version 1.1 (the "License"); you may not use this file
4 * except in compliance with the License. You may obtain a copy of
5 * the License at http://www.mozilla.org/MPL/
6 *
7 * Software distributed under the License is distributed on an "AS
8 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9 * implied. See the License for the specific language governing
10 * rights and limitations under the License.
11 *
12 * The Original Code is the Netscape security libraries.
13 *
14 * The Initial Developer of the Original Code is Netscape
15 * Communications Corporation.  Portions created by Netscape are
16 * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
17 * Rights Reserved.
18 *
19 * Contributor(s):
20 *
21 * Alternatively, the contents of this file may be used under the
22 * terms of the GNU General Public License Version 2 or later (the
23 * "GPL"), in which case the provisions of the GPL are applicable
24 * instead of those above.  If you wish to allow use of your
25 * version of this file only under the terms of the GPL and not to
26 * allow others to use your version of this file under the MPL,
27 * indicate your decision by deleting the provisions above and
28 * replace them with the notice and other provisions required by
29 * the GPL.  If you do not delete the provisions above, a recipient
30 * may use your version of this file under either the MPL or the
31 * GPL.
32 */
33
34/*
35 * CMS digestedData methods.
36 */
37
38#include <Security/SecCmsDigestedData.h>
39
40#include <Security/SecCmsContentInfo.h>
41#include <Security/SecCmsDigestContext.h>
42
43#include "cmslocal.h"
44
45#include "secitem.h"
46#include "secoid.h"
47#include <security_asn1/secasn1.h>
48#include <security_asn1/secerr.h>
49
50/*
51 * SecCmsDigestedDataCreate - create a digestedData object (presumably for encoding)
52 *
53 * version will be set by SecCmsDigestedDataEncodeBeforeStart
54 * digestAlg is passed as parameter
55 * contentInfo must be filled by the user
56 * digest will be calculated while encoding
57 */
58SecCmsDigestedDataRef
59SecCmsDigestedDataCreate(SecCmsMessageRef cmsg, SECAlgorithmID *digestalg)
60{
61    void *mark;
62    SecCmsDigestedDataRef digd;
63    PLArenaPool *poolp;
64
65    poolp = cmsg->poolp;
66
67    mark = PORT_ArenaMark(poolp);
68
69    digd = (SecCmsDigestedDataRef)PORT_ArenaZAlloc(poolp, sizeof(SecCmsDigestedData));
70    if (digd == NULL)
71	goto loser;
72
73    digd->cmsg = cmsg;
74
75    if (SECOID_CopyAlgorithmID (poolp, &(digd->digestAlg), digestalg) != SECSuccess)
76	goto loser;
77
78    PORT_ArenaUnmark(poolp, mark);
79    return digd;
80
81loser:
82    PORT_ArenaRelease(poolp, mark);
83    return NULL;
84}
85
86/*
87 * SecCmsDigestedDataDestroy - destroy a digestedData object
88 */
89void
90SecCmsDigestedDataDestroy(SecCmsDigestedDataRef digd)
91{
92    /* everything's in a pool, so don't worry about the storage */
93    SecCmsContentInfoDestroy(&(digd->contentInfo));
94    return;
95}
96
97/*
98 * SecCmsDigestedDataGetContentInfo - return pointer to digestedData object's contentInfo
99 */
100SecCmsContentInfoRef
101SecCmsDigestedDataGetContentInfo(SecCmsDigestedDataRef digd)
102{
103    return &(digd->contentInfo);
104}
105
106/*
107 * SecCmsDigestedDataEncodeBeforeStart - do all the necessary things to a DigestedData
108 *     before encoding begins.
109 *
110 * In particular:
111 *  - set the right version number. The contentInfo's content type must be set up already.
112 */
113OSStatus
114SecCmsDigestedDataEncodeBeforeStart(SecCmsDigestedDataRef digd)
115{
116    unsigned long version;
117    CSSM_DATA_PTR dummy;
118
119    version = SEC_CMS_DIGESTED_DATA_VERSION_DATA;
120    if (SecCmsContentInfoGetContentTypeTag(&(digd->contentInfo)) != SEC_OID_PKCS7_DATA)
121	version = SEC_CMS_DIGESTED_DATA_VERSION_ENCAP;
122
123    dummy = SEC_ASN1EncodeInteger(digd->cmsg->poolp, &(digd->version), version);
124    return (dummy == NULL) ? SECFailure : SECSuccess;
125}
126
127/*
128 * SecCmsDigestedDataEncodeBeforeData - do all the necessary things to a DigestedData
129 *     before the encapsulated data is passed through the encoder.
130 *
131 * In detail:
132 *  - set up the digests if necessary
133 */
134OSStatus
135SecCmsDigestedDataEncodeBeforeData(SecCmsDigestedDataRef digd)
136{
137    /* set up the digests */
138    if (digd->digestAlg.algorithm.Length != 0 && digd->digest.Length == 0) {
139	/* if digest is already there, do nothing */
140	digd->contentInfo.digcx = SecCmsDigestContextStartSingle(&(digd->digestAlg));
141	if (digd->contentInfo.digcx == NULL)
142	    return SECFailure;
143    }
144    return SECSuccess;
145}
146
147/*
148 * SecCmsDigestedDataEncodeAfterData - do all the necessary things to a DigestedData
149 *     after all the encapsulated data was passed through the encoder.
150 *
151 * In detail:
152 *  - finish the digests
153 */
154OSStatus
155SecCmsDigestedDataEncodeAfterData(SecCmsDigestedDataRef digd)
156{
157    OSStatus rv = SECSuccess;
158    /* did we have digest calculation going on? */
159    if (digd->contentInfo.digcx) {
160	rv = SecCmsDigestContextFinishSingle(digd->contentInfo.digcx,
161					     (SecArenaPoolRef)digd->cmsg->poolp, &(digd->digest));
162	/* error has been set by SecCmsDigestContextFinishSingle */
163	digd->contentInfo.digcx = NULL;
164    }
165
166    return rv;
167}
168
169/*
170 * SecCmsDigestedDataDecodeBeforeData - do all the necessary things to a DigestedData
171 *     before the encapsulated data is passed through the encoder.
172 *
173 * In detail:
174 *  - set up the digests if necessary
175 */
176OSStatus
177SecCmsDigestedDataDecodeBeforeData(SecCmsDigestedDataRef digd)
178{
179    /* is there a digest algorithm yet? */
180    if (digd->digestAlg.algorithm.Length == 0)
181	return SECFailure;
182
183    digd->contentInfo.digcx = SecCmsDigestContextStartSingle(&(digd->digestAlg));
184    if (digd->contentInfo.digcx == NULL)
185	return SECFailure;
186
187    return SECSuccess;
188}
189
190/*
191 * SecCmsDigestedDataDecodeAfterData - do all the necessary things to a DigestedData
192 *     after all the encapsulated data was passed through the encoder.
193 *
194 * In detail:
195 *  - finish the digests
196 */
197OSStatus
198SecCmsDigestedDataDecodeAfterData(SecCmsDigestedDataRef digd)
199{
200    OSStatus rv = SECSuccess;
201    /* did we have digest calculation going on? */
202    if (digd->contentInfo.digcx) {
203	rv = SecCmsDigestContextFinishSingle(digd->contentInfo.digcx,
204					     (SecArenaPoolRef)digd->cmsg->poolp, &(digd->cdigest));
205	/* error has been set by SecCmsDigestContextFinishSingle */
206	digd->contentInfo.digcx = NULL;
207    }
208
209    return rv;
210}
211
212/*
213 * SecCmsDigestedDataDecodeAfterEnd - finalize a digestedData.
214 *
215 * In detail:
216 *  - check the digests for equality
217 */
218OSStatus
219SecCmsDigestedDataDecodeAfterEnd(SecCmsDigestedDataRef digd)
220{
221    /* did we have digest calculation going on? */
222    if (digd->cdigest.Length != 0) {
223	/* XXX comparision btw digest & cdigest */
224	/* XXX set status */
225	/* TODO!!!! */
226    }
227
228    return SECSuccess;
229}
230