|
1 /** |
|
2 * XMLSec library |
|
3 * |
|
4 * This is free software; see Copyright file in the source |
|
5 * distribution for preciese wording. |
|
6 * |
|
7 * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com> |
|
8 * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. |
|
9 */ |
|
10 #include "xmlsecc_globals.h" |
|
11 |
|
12 #include <string.h> |
|
13 #include <e32err.h> |
|
14 #include "xmlsecc_config.h" |
|
15 #include "xmlsec_xmlsec.h" |
|
16 #include "xmlsec_keys.h" |
|
17 #include "xmlsec_transforms.h" |
|
18 #include "xmlsec_errors.h" |
|
19 #include "xmlsec_error_flag.h" |
|
20 |
|
21 #include "xmlsecc_app.h" |
|
22 #include "xmlsecc_crypto.h" |
|
23 #include "xmlsecc_cryptowrapper.h" // replace gnutils/gnutls.h |
|
24 |
|
25 //#define XMLSEC_SYMBIAN_MAX_DIGEST_SIZE 32 |
|
26 |
|
27 /************************************************************************** |
|
28 * |
|
29 * Internal SymbianCrypto Digest CTX |
|
30 * |
|
31 *****************************************************************************/ |
|
32 typedef struct _xmlSecSymbianCryptoDigestCtx |
|
33 xmlSecSymbianCryptoDigestCtx, *xmlSecSymbianCryptoDigestCtxPtr; |
|
34 struct _xmlSecSymbianCryptoDigestCtx { |
|
35 int digest; |
|
36 ScMDHd digestCtx; |
|
37 xmlSecByte dgst[XMLSEC_SYMBIAN_MAX_DIGEST_SIZE]; |
|
38 xmlSecSize dgstSize; /* dgst size in bytes */ |
|
39 }; |
|
40 |
|
41 xmlSecTransformGetDataTypeMethod const xmlSecCrpytoGetDataTypeMethod = xmlSecTransformDefaultGetDataType; |
|
42 xmlSecTransformPushBinMethod const xmlSecCryptoPushBinMethod = xmlSecTransformDefaultPushBin; |
|
43 xmlSecTransformPopBinMethod const xmlSecCryptoPopBinMethod = xmlSecTransformDefaultPopBin; |
|
44 |
|
45 /****************************************************************************** |
|
46 * |
|
47 * Digest transforms |
|
48 * |
|
49 * xmlSecSymbianCryptoDigestCtx is located after xmlSecTransform |
|
50 * |
|
51 *****************************************************************************/ |
|
52 #define xmlSecSymbianCryptoDigestSize \ |
|
53 (sizeof(xmlSecTransform) + sizeof(xmlSecSymbianCryptoDigestCtx)) |
|
54 #define xmlSecSymbianCryptoDigestGetCtx(transform) \ |
|
55 ((xmlSecSymbianCryptoDigestCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform))) |
|
56 |
|
57 static int xmlSecSymbianCryptoDigestInitialize (xmlSecTransformPtr transform); |
|
58 static void xmlSecSymbianCryptoDigestFinalize (xmlSecTransformPtr transform); |
|
59 static int xmlSecSymbianCryptoDigestVerify (xmlSecTransformPtr transform, |
|
60 const xmlSecByte* data, |
|
61 xmlSecSize dataSize, |
|
62 xmlSecTransformCtxPtr transformCtx); |
|
63 static int xmlSecSymbianCryptoDigestExecute (xmlSecTransformPtr transform, |
|
64 int last, |
|
65 xmlSecTransformCtxPtr transformCtx); |
|
66 static int xmlSecSymbianCryptoDigestCheckId (xmlSecTransformPtr transform); |
|
67 |
|
68 static int |
|
69 xmlSecSymbianCryptoDigestCheckId(xmlSecTransformPtr transform) { |
|
70 |
|
71 #ifndef XMLSEC_NO_SHA1 |
|
72 if(xmlSecTransformCheckId(transform, xmlSecSymbianCryptoTransformSha1Id)) { |
|
73 return(1); |
|
74 } |
|
75 #endif /* XMLSEC_NO_SHA1 */ |
|
76 |
|
77 return(0); |
|
78 } |
|
79 |
|
80 static int |
|
81 xmlSecSymbianCryptoDigestInitialize(xmlSecTransformPtr transform) { |
|
82 xmlSecSymbianCryptoDigestCtxPtr ctx; |
|
83 #ifndef XMLSEC_GNUTLS_OLD |
|
84 TInt ret; |
|
85 #endif /* XMLSEC_GNUTLS_OLD */ |
|
86 |
|
87 xmlSecAssert2(xmlSecSymbianCryptoDigestCheckId(transform), -1); |
|
88 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoDigestSize), -1); |
|
89 |
|
90 ctx = xmlSecSymbianCryptoDigestGetCtx(transform); |
|
91 xmlSecAssert2(ctx, -1); |
|
92 |
|
93 /* initialize context */ |
|
94 memset(ctx, 0, sizeof(xmlSecSymbianCryptoDigestCtx)); |
|
95 |
|
96 #ifndef XMLSEC_NO_SHA1 |
|
97 if(xmlSecTransformCheckId(transform, xmlSecSymbianCryptoTransformSha1Id)) { |
|
98 ctx->digest = SC_MD_SHA1; |
|
99 } else |
|
100 #endif /* XMLSEC_NO_SHA1 */ |
|
101 |
|
102 if(1) { |
|
103 xmlSecError(XMLSEC_ERRORS_HERE, |
|
104 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
105 NULL, |
|
106 XMLSEC_ERRORS_R_INVALID_TRANSFORM, |
|
107 XMLSEC_ERRORS_NO_MESSAGE); |
|
108 return(-1); |
|
109 } |
|
110 |
|
111 #ifndef XMLSEC_GNUTLS_OLD |
|
112 ret = sc_md_open(&ctx->digestCtx, ctx->digest, SC_MD_FLAG_SECURE); /* we are paranoid */ |
|
113 if(ret != KErrNone) { |
|
114 #else /* XMLSEC_GNUTLS_OLD */ |
|
115 ctx->digestCtx = sc_md_open(ctx->digest, SC_MD_FLAG_SECURE); /* we are paranoid */ |
|
116 if(!ctx->digestCtx) { |
|
117 #endif /* XMLSEC_GNUTLS_OLD */ |
|
118 if ( ret != KErrNone ) |
|
119 { |
|
120 xmlSecSetErrorFlag( ret ); |
|
121 } |
|
122 xmlSecError(XMLSEC_ERRORS_HERE, |
|
123 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
124 "sc_md_open", |
|
125 XMLSEC_ERRORS_R_CRYPTO_FAILED, |
|
126 XMLSEC_ERRORS_NO_MESSAGE); |
|
127 return(-1); |
|
128 } |
|
129 return(0); |
|
130 } |
|
131 |
|
132 static void |
|
133 xmlSecSymbianCryptoDigestFinalize(xmlSecTransformPtr transform) { |
|
134 xmlSecSymbianCryptoDigestCtxPtr ctx; |
|
135 |
|
136 xmlSecAssert(xmlSecSymbianCryptoDigestCheckId(transform)); |
|
137 xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoDigestSize)); |
|
138 |
|
139 ctx = xmlSecSymbianCryptoDigestGetCtx(transform); |
|
140 xmlSecAssert(ctx); |
|
141 |
|
142 if(ctx->digestCtx) { |
|
143 sc_md_close(ctx->digestCtx); |
|
144 } |
|
145 memset(ctx, 0, sizeof(xmlSecSymbianCryptoDigestCtx)); |
|
146 } |
|
147 |
|
148 static int |
|
149 xmlSecSymbianCryptoDigestVerify(xmlSecTransformPtr transform, |
|
150 const xmlSecByte* data, xmlSecSize dataSize, |
|
151 xmlSecTransformCtxPtr transformCtx) { |
|
152 xmlSecSymbianCryptoDigestCtxPtr ctx; |
|
153 |
|
154 xmlSecAssert2(xmlSecSymbianCryptoDigestCheckId(transform), -1); |
|
155 xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1); |
|
156 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoDigestSize), -1); |
|
157 xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1); |
|
158 xmlSecAssert2(data, -1); |
|
159 xmlSecAssert2(transformCtx, -1); |
|
160 |
|
161 ctx = xmlSecSymbianCryptoDigestGetCtx(transform); |
|
162 xmlSecAssert2(ctx, -1); |
|
163 xmlSecAssert2(ctx->dgstSize > 0, -1); |
|
164 |
|
165 if(dataSize != ctx->dgstSize) { |
|
166 xmlSecError(XMLSEC_ERRORS_HERE, |
|
167 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
168 NULL, |
|
169 XMLSEC_ERRORS_R_INVALID_DATA, |
|
170 "data and digest sizes are different (data=%d, dgst=%d)", |
|
171 dataSize, ctx->dgstSize); |
|
172 transform->status = xmlSecTransformStatusFail; |
|
173 return(0); |
|
174 } |
|
175 |
|
176 if(memcmp(ctx->dgst, data, dataSize) != 0) { |
|
177 xmlSecError(XMLSEC_ERRORS_HERE, |
|
178 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
179 NULL, |
|
180 XMLSEC_ERRORS_R_INVALID_DATA, |
|
181 "data and digest do not match"); |
|
182 transform->status = xmlSecTransformStatusFail; |
|
183 return(0); |
|
184 } |
|
185 |
|
186 transform->status = xmlSecTransformStatusOk; |
|
187 return(0); |
|
188 } |
|
189 |
|
190 static int |
|
191 xmlSecSymbianCryptoDigestExecute(xmlSecTransformPtr transform, |
|
192 int last, |
|
193 xmlSecTransformCtxPtr transformCtx) { |
|
194 xmlSecSymbianCryptoDigestCtxPtr ctx; |
|
195 xmlSecBufferPtr in, out; |
|
196 int ret; |
|
197 |
|
198 xmlSecAssert2(xmlSecSymbianCryptoDigestCheckId(transform), -1); |
|
199 xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) |
|
200 || (transform->operation == xmlSecTransformOperationVerify), -1); |
|
201 xmlSecAssert2(transformCtx, -1); |
|
202 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecSymbianCryptoDigestSize), -1); |
|
203 |
|
204 ctx = xmlSecSymbianCryptoDigestGetCtx(transform); |
|
205 xmlSecAssert2(ctx, -1); |
|
206 xmlSecAssert2(ctx->digest != SC_MD_NONE, -1); |
|
207 xmlSecAssert2(ctx->digestCtx, -1); |
|
208 |
|
209 in = &(transform->inBuf); |
|
210 out = &(transform->outBuf); |
|
211 |
|
212 if(transform->status == xmlSecTransformStatusNone) { |
|
213 transform->status = xmlSecTransformStatusWorking; |
|
214 } |
|
215 |
|
216 if(transform->status == xmlSecTransformStatusWorking) { |
|
217 xmlSecSize inSize; |
|
218 |
|
219 inSize = xmlSecBufferGetSize(in); |
|
220 if(inSize > 0) { |
|
221 sc_md_write(ctx->digestCtx, xmlSecBufferGetData(in), inSize); |
|
222 |
|
223 ret = xmlSecBufferRemoveHead(in, inSize); |
|
224 if(ret < 0) { |
|
225 xmlSecError(XMLSEC_ERRORS_HERE, |
|
226 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
227 "xmlSecBufferRemoveHead", |
|
228 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
229 "size=%d", inSize); |
|
230 return(-1); |
|
231 } |
|
232 } |
|
233 if(last) { |
|
234 const xmlSecByte* buf; |
|
235 |
|
236 /* get the final digest */ |
|
237 sc_md_final(ctx->digestCtx); |
|
238 |
|
239 /* get length before sc_md_read */ |
|
240 ctx->dgstSize = sc_md_get_algo_dlen(ctx->digestCtx); |
|
241 xmlSecAssert2(ctx->dgstSize > 0, -1); |
|
242 xmlSecAssert2(ctx->dgstSize <= sizeof(ctx->dgst), -1); |
|
243 |
|
244 buf = sc_md_read(ctx->digestCtx, ctx->digest); |
|
245 if(!buf) { |
|
246 xmlSecError(XMLSEC_ERRORS_HERE, |
|
247 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
248 "sc_md_read", |
|
249 XMLSEC_ERRORS_R_CRYPTO_FAILED, |
|
250 XMLSEC_ERRORS_NO_MESSAGE); |
|
251 return(-1); |
|
252 } |
|
253 |
|
254 /* copy it to our internal buffer */ |
|
255 memcpy(ctx->dgst, buf, ctx->dgstSize); |
|
256 |
|
257 /* and to the output if needed */ |
|
258 if(transform->operation == xmlSecTransformOperationSign) { |
|
259 ret = xmlSecBufferAppend(out, ctx->dgst, ctx->dgstSize); |
|
260 if(ret < 0) { |
|
261 xmlSecError(XMLSEC_ERRORS_HERE, |
|
262 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
263 "xmlSecBufferAppend", |
|
264 XMLSEC_ERRORS_R_XMLSEC_FAILED, |
|
265 "size=%d", ctx->dgstSize); |
|
266 return(-1); |
|
267 } |
|
268 } |
|
269 transform->status = xmlSecTransformStatusFinished; |
|
270 } |
|
271 } else if(transform->status == xmlSecTransformStatusFinished) { |
|
272 /* the only way we can get here is if there is no input */ |
|
273 xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1); |
|
274 } else { |
|
275 xmlSecError(XMLSEC_ERRORS_HERE, |
|
276 xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), |
|
277 NULL, |
|
278 XMLSEC_ERRORS_R_INVALID_STATUS, |
|
279 "status=%d", transform->status); |
|
280 return(-1); |
|
281 } |
|
282 |
|
283 return(0); |
|
284 } |
|
285 |
|
286 #ifndef XMLSEC_NO_SHA1 |
|
287 /****************************************************************************** |
|
288 * |
|
289 * SHA1 Digest transforms |
|
290 * |
|
291 *****************************************************************************/ |
|
292 static xmlSecTransformKlass xmlSecSymbianCryptoSha1Klass = { |
|
293 /* klass/object sizes */ |
|
294 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */ |
|
295 xmlSecSymbianCryptoDigestSize, /* xmlSecSize objSize */ |
|
296 |
|
297 /* data */ |
|
298 xmlSecNameSha1, /* const xmlChar* name; */ |
|
299 xmlSecHrefSha1, /* const xmlChar* href; */ |
|
300 xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */ |
|
301 |
|
302 /* methods */ |
|
303 xmlSecSymbianCryptoDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */ |
|
304 xmlSecSymbianCryptoDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */ |
|
305 NULL, /* xmlSecTransformNodeReadMethod readNode; */ |
|
306 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */ |
|
307 NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */ |
|
308 NULL, /* xmlSecTransformSetKeyMethod setKey; */ |
|
309 xmlSecSymbianCryptoDigestVerify, /* xmlSecTransformVerifyMethod verify; */ |
|
310 xmlSecCrpytoGetDataTypeMethod, /* xmlSecTransformGetDataTypeMethod getDataType; */ |
|
311 xmlSecCryptoPushBinMethod, /* xmlSecTransformPushBinMethod pushBin; */ |
|
312 xmlSecCryptoPopBinMethod, /* xmlSecTransformPopBinMethod popBin; */ |
|
313 NULL, /* xmlSecTransformPushXmlMethod pushXml; */ |
|
314 NULL, /* xmlSecTransformPopXmlMethod popXml; */ |
|
315 xmlSecSymbianCryptoDigestExecute, /* xmlSecTransformExecuteMethod execute; */ |
|
316 |
|
317 NULL, /* void* reserved0; */ |
|
318 NULL, /* void* reserved1; */ |
|
319 }; |
|
320 |
|
321 /** |
|
322 * xmlSecSymbianCryptoTransformSha1GetKlass: |
|
323 * |
|
324 * SHA-1 digest transform klass. |
|
325 * |
|
326 * Returns pointer to SHA-1 digest transform klass. |
|
327 */ |
|
328 EXPORT_C |
|
329 xmlSecTransformId |
|
330 xmlSecSymbianCryptoTransformSha1GetKlass(void) { |
|
331 return(&xmlSecSymbianCryptoSha1Klass); |
|
332 } |
|
333 #endif /* XMLSEC_NO_SHA1 */ |
|
334 |
|
335 |
|
336 |
|
337 |