1 /*
2 * XML Security Library (http://www.aleksey.com/xmlsec).
3 *
4 *
5 * This is free software; see Copyright file in the source
6 * distribution for preciese wording.
7 *
8 * Copyright (C) 2018 Miklos Vajna. All Rights Reserved.
9 */
10 /**
11 * SECTION:digests
12 * @Short_description: Digests transforms implementation for Microsoft Cryptography API: Next Generation (CNG).
13 * @Stability: Private
14 *
15 */
16
17 #include "globals.h"
18
19 #include <string.h>
20
21 #define WIN32_NO_STATUS
22 #include <windows.h>
23 #undef WIN32_NO_STATUS
24 #include <ntstatus.h>
25 #include <bcrypt.h>
26
27 #include <xmlsec/xmlsec.h>
28 #include <xmlsec/keys.h>
29 #include <xmlsec/transforms.h>
30 #include <xmlsec/errors.h>
31 #include <xmlsec/strings.h>
32
33 #include <xmlsec/mscng/crypto.h>
34
35 typedef struct _xmlSecMSCngDigestCtx xmlSecMSCngDigestCtx, *xmlSecMSCngDigestCtxPtr;
36 struct _xmlSecMSCngDigestCtx {
37 LPCWSTR pszAlgId;
38 DWORD cbHash;
39 PBYTE pbHash;
40 BCRYPT_ALG_HANDLE hAlg;
41 PBYTE pbHashObject;
42 BCRYPT_HASH_HANDLE hHash;
43 };
44
45 /******************************************************************************
46 *
47 * MSCng Digest transforms
48 *
49 * xmlSecMSCngDigestCtx is located after xmlSecTransform
50 *
51 *****************************************************************************/
52 #define xmlSecMSCngDigestSize \
53 (sizeof(xmlSecTransform) + sizeof(xmlSecMSCngDigestCtx))
54 #define xmlSecMSCngDigestGetCtx(transform) \
55 ((xmlSecMSCngDigestCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
56
57
58 static int xmlSecMSCngDigestInitialize (xmlSecTransformPtr transform);
59 static void xmlSecMSCngDigestFinalize (xmlSecTransformPtr transform);
60 static int xmlSecMSCngDigestVerify (xmlSecTransformPtr transform,
61 const xmlSecByte* data,
62 xmlSecSize dataSize,
63 xmlSecTransformCtxPtr transformCtx);
64 static int xmlSecMSCngDigestExecute (xmlSecTransformPtr transform,
65 int last,
66 xmlSecTransformCtxPtr transformCtx);
67 static int xmlSecMSCngDigestCheckId (xmlSecTransformPtr transform);
68
69
70 static int
xmlSecMSCngDigestCheckId(xmlSecTransformPtr transform)71 xmlSecMSCngDigestCheckId(xmlSecTransformPtr transform) {
72
73 #ifndef XMLSEC_NO_MD5
74 if(xmlSecTransformCheckId(transform, xmlSecMSCngTransformMd5Id)) {
75 return(1);
76 } else
77 #endif /* XMLSEC_NO_MD5 */
78 #ifndef XMLSEC_NO_SHA1
79 if(xmlSecTransformCheckId(transform, xmlSecMSCngTransformSha1Id)) {
80 return(1);
81 } else
82 #endif /* XMLSEC_NO_SHA1 */
83 #ifndef XMLSEC_NO_SHA256
84 if(xmlSecTransformCheckId(transform, xmlSecMSCngTransformSha256Id)) {
85 return(1);
86 } else
87 #endif /* XMLSEC_NO_SHA256 */
88 #ifndef XMLSEC_NO_SHA384
89 if(xmlSecTransformCheckId(transform, xmlSecMSCngTransformSha384Id)) {
90 return(1);
91 } else
92 #endif /* XMLSEC_NO_SHA384 */
93 #ifndef XMLSEC_NO_SHA512
94 if(xmlSecTransformCheckId(transform, xmlSecMSCngTransformSha512Id)) {
95 return(1);
96 } else
97 #endif /* XMLSEC_NO_SHA512 */
98
99 return(0);
100 }
101
102 static int
xmlSecMSCngDigestInitialize(xmlSecTransformPtr transform)103 xmlSecMSCngDigestInitialize(xmlSecTransformPtr transform) {
104 xmlSecMSCngDigestCtxPtr ctx;
105
106 xmlSecAssert2(xmlSecMSCngDigestCheckId(transform), -1);
107 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCngDigestSize), -1);
108
109 ctx = xmlSecMSCngDigestGetCtx(transform);
110 xmlSecAssert2(ctx != NULL, -1);
111
112 /* initialize context */
113 memset(ctx, 0, sizeof(xmlSecMSCngDigestCtx));
114
115 #ifndef XMLSEC_NO_MD5
116 if(xmlSecTransformCheckId(transform, xmlSecMSCngTransformMd5Id)) {
117 ctx->pszAlgId = BCRYPT_MD5_ALGORITHM;
118 } else
119 #endif /* XMLSEC_NO_MD5 */
120
121 #ifndef XMLSEC_NO_SHA1
122 if(xmlSecTransformCheckId(transform, xmlSecMSCngTransformSha1Id)) {
123 ctx->pszAlgId = BCRYPT_SHA1_ALGORITHM;
124 } else
125 #endif /* XMLSEC_NO_SHA1 */
126
127 #ifndef XMLSEC_NO_SHA256
128 if(xmlSecTransformCheckId(transform, xmlSecMSCngTransformSha256Id)) {
129 ctx->pszAlgId = BCRYPT_SHA256_ALGORITHM;
130 } else
131 #endif /* XMLSEC_NO_SHA256 */
132
133 #ifndef XMLSEC_NO_SHA384
134 if(xmlSecTransformCheckId(transform, xmlSecMSCngTransformSha384Id)) {
135 ctx->pszAlgId = BCRYPT_SHA384_ALGORITHM;
136 } else
137 #endif /* XMLSEC_NO_SHA384 */
138
139 #ifndef XMLSEC_NO_SHA512
140 if(xmlSecTransformCheckId(transform, xmlSecMSCngTransformSha512Id)) {
141 ctx->pszAlgId = BCRYPT_SHA512_ALGORITHM;
142 } else
143 #endif /* XMLSEC_NO_SHA512 */
144
145 {
146 xmlSecInvalidTransfromError(transform);
147 return(-1);
148 }
149
150 return(0);
151 }
152
xmlSecMSCngDigestFinalize(xmlSecTransformPtr transform)153 static void xmlSecMSCngDigestFinalize(xmlSecTransformPtr transform) {
154 xmlSecMSCngDigestCtxPtr ctx;
155
156 xmlSecAssert(xmlSecMSCngDigestCheckId(transform));
157 xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecMSCngDigestSize));
158
159 ctx = xmlSecMSCngDigestGetCtx(transform);
160 xmlSecAssert(ctx != NULL);
161
162 if(ctx->hAlg != 0) {
163 BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
164 }
165
166 if(ctx->hHash != 0) {
167 BCryptDestroyHash(ctx->hHash);
168 }
169
170 if(ctx->pbHashObject != NULL) {
171 xmlFree(ctx->pbHashObject);
172 }
173
174 if(ctx->pbHash != NULL) {
175 xmlFree(ctx->pbHash);
176 }
177
178 memset(ctx, 0, sizeof(xmlSecMSCngDigestCtx));
179 }
180
181 static int
xmlSecMSCngDigestVerify(xmlSecTransformPtr transform,const xmlSecByte * data,xmlSecSize dataSize,xmlSecTransformCtxPtr transformCtx)182 xmlSecMSCngDigestVerify(xmlSecTransformPtr transform,
183 const xmlSecByte* data,
184 xmlSecSize dataSize,
185 xmlSecTransformCtxPtr transformCtx) {
186 xmlSecMSCngDigestCtxPtr ctx;
187
188 xmlSecAssert2(xmlSecMSCngDigestCheckId(transform), -1);
189 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCngDigestSize), -1);
190 xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1);
191 xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1);
192 xmlSecAssert2(data != NULL, -1);
193 xmlSecAssert2(transformCtx != NULL, -1);
194
195 ctx = xmlSecMSCngDigestGetCtx(transform);
196 xmlSecAssert2(ctx != NULL, -1);
197 xmlSecAssert2(ctx->cbHash > 0, -1);
198
199 if(dataSize != ctx->cbHash) {
200 xmlSecInvalidSizeError("Digest", dataSize, ctx->cbHash,
201 xmlSecTransformGetName(transform));
202 transform->status = xmlSecTransformStatusFail;
203 return(0);
204 }
205
206 if(memcmp(ctx->pbHash, data, ctx->cbHash) != 0) {
207 xmlSecInvalidDataError("data and digest do not match",
208 xmlSecTransformGetName(transform));
209 transform->status = xmlSecTransformStatusFail;
210 return(0);
211 }
212
213 transform->status = xmlSecTransformStatusOk;
214 return(0);
215 }
216
217 static int
xmlSecMSCngDigestExecute(xmlSecTransformPtr transform,int last,xmlSecTransformCtxPtr transformCtx)218 xmlSecMSCngDigestExecute(xmlSecTransformPtr transform,
219 int last,
220 xmlSecTransformCtxPtr transformCtx) {
221 xmlSecMSCngDigestCtxPtr ctx;
222 xmlSecBufferPtr in, out;
223 NTSTATUS status;
224 int ret;
225 DWORD cbData = 0;
226 DWORD cbHashObject = 0;
227
228 xmlSecAssert2(xmlSecMSCngDigestCheckId(transform), -1);
229 xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
230 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCngDigestSize), -1);
231 xmlSecAssert2(transformCtx != NULL, -1);
232
233 in = &(transform->inBuf);
234 xmlSecAssert2(in != NULL, -1);
235
236 out = &(transform->outBuf);
237 xmlSecAssert2(out != NULL, -1);
238
239 ctx = xmlSecMSCngDigestGetCtx(transform);
240 xmlSecAssert2(ctx != NULL, -1);
241
242 if(transform->status == xmlSecTransformStatusNone) {
243 /* open an algorithm handle */
244 status = BCryptOpenAlgorithmProvider(
245 &ctx->hAlg,
246 ctx->pszAlgId,
247 NULL,
248 0);
249 if(status != STATUS_SUCCESS) {
250 xmlSecMSCngNtError("BCryptOpenAlgorithmProvider", xmlSecTransformGetName(transform), status);
251 return(-1);
252 }
253
254 /* calculate the size of the buffer to hold the hash object */
255 status = BCryptGetProperty(
256 ctx->hAlg,
257 BCRYPT_OBJECT_LENGTH,
258 (PBYTE)&cbHashObject,
259 sizeof(DWORD),
260 &cbData,
261 0);
262 if(status != STATUS_SUCCESS) {
263 xmlSecMSCngNtError("BCryptGetProperty", xmlSecTransformGetName(transform), status);
264 return(-1);
265 }
266
267 /* allocate the hash object on the heap */
268 ctx->pbHashObject = (PBYTE)xmlMalloc(cbHashObject);
269 if(ctx->pbHashObject == NULL) {
270 xmlSecMallocError(cbHashObject, NULL);
271 return(-1);
272 }
273
274 /* calculate the length of the hash */
275 status = BCryptGetProperty(
276 ctx->hAlg,
277 BCRYPT_HASH_LENGTH,
278 (PBYTE)&ctx->cbHash,
279 sizeof(DWORD),
280 &cbData,
281 0);
282 if(status != STATUS_SUCCESS) {
283 xmlSecMSCngNtError("BCryptGetProperty", xmlSecTransformGetName(transform), status);
284 return(-1);
285 }
286
287 /* allocate the hash buffer on the heap */
288 ctx->pbHash = (PBYTE)xmlMalloc(ctx->cbHash);
289 if(ctx->pbHash == NULL) {
290 xmlSecMallocError(ctx->cbHash, NULL);
291 return(-1);
292 }
293
294 /* create the hash */
295 status = BCryptCreateHash(
296 ctx->hAlg,
297 &ctx->hHash,
298 ctx->pbHashObject,
299 cbHashObject,
300 NULL,
301 0,
302 0);
303 if(status != STATUS_SUCCESS) {
304 xmlSecMSCngNtError("BCryptCreateHash", xmlSecTransformGetName(transform), status);
305 return(-1);
306 }
307
308 transform->status = xmlSecTransformStatusWorking;
309 }
310
311 if(transform->status == xmlSecTransformStatusWorking) {
312 xmlSecSize inSize;
313
314 inSize = xmlSecBufferGetSize(in);
315 if(inSize > 0) {
316 /* hash some data */
317 status = BCryptHashData(
318 ctx->hHash,
319 (PBYTE)xmlSecBufferGetData(in),
320 inSize,
321 0);
322 if(status != STATUS_SUCCESS) {
323 xmlSecMSCngNtError("BCryptHashData", xmlSecTransformGetName(transform), status);
324 return(-1);
325 }
326
327 ret = xmlSecBufferRemoveHead(in, inSize);
328 if(ret < 0) {
329 xmlSecInternalError("xmlSecBufferRemoveHead",
330 xmlSecTransformGetName(transform));
331 return(-1);
332 }
333 }
334
335 if(last) {
336 /* close the hash */
337 status = BCryptFinishHash(
338 ctx->hHash,
339 ctx->pbHash,
340 ctx->cbHash,
341 0);
342 if(status != STATUS_SUCCESS) {
343 xmlSecMSCngNtError("BCryptFinishHash", xmlSecTransformGetName(transform), status);
344 return(-1);
345 }
346
347 xmlSecAssert2(ctx->cbHash > 0, -1);
348
349 /* copy result to output */
350 if(transform->operation == xmlSecTransformOperationSign) {
351 ret = xmlSecBufferAppend(out, ctx->pbHash, ctx->cbHash);
352 if(ret < 0) {
353 xmlSecInternalError("xmlSecBufferAppend",
354 xmlSecTransformGetName(transform));
355 return(-1);
356 }
357 }
358 transform->status = xmlSecTransformStatusFinished;
359 }
360 } else if(transform->status == xmlSecTransformStatusFinished) {
361 xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1);
362 } else {
363 xmlSecInvalidTransfromStatusError(transform);
364 return(-1);
365 }
366
367 return(0);
368 }
369
370 #ifndef XMLSEC_NO_MD5
371 /******************************************************************************
372 *
373 * MD5
374 *
375 *****************************************************************************/
376 static xmlSecTransformKlass xmlSecMSCngMd5Klass = {
377 /* klass/object sizes */
378 sizeof(xmlSecTransformKlass), /* size_t klassSize */
379 xmlSecMSCngDigestSize, /* size_t objSize */
380
381 xmlSecNameMd5, /* const xmlChar* name; */
382 xmlSecHrefMd5, /* const xmlChar* href; */
383 xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
384 xmlSecMSCngDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
385 xmlSecMSCngDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
386 NULL, /* xmlSecTransformNodeReadMethod readNode; */
387 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
388 NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
389 NULL, /* xmlSecTransformSetKeyMethod setKey; */
390 xmlSecMSCngDigestVerify, /* xmlSecTransformVerifyMethod verify; */
391 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
392 xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
393 xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
394 NULL, /* xmlSecTransformPushXmlMethod pushXml; */
395 NULL, /* xmlSecTransformPopXmlMethod popXml; */
396 xmlSecMSCngDigestExecute, /* xmlSecTransformExecuteMethod execute; */
397 NULL, /* void* reserved0; */
398 NULL, /* void* reserved1; */
399 };
400
401 /**
402 * xmlSecMSCngTransformMd5GetKlass:
403 *
404 * MD-5 digest transform klass.
405 *
406 * Returns: pointer to MD-5 digest transform klass.
407 */
408 xmlSecTransformId
xmlSecMSCngTransformMd5GetKlass(void)409 xmlSecMSCngTransformMd5GetKlass(void) {
410 return(&xmlSecMSCngMd5Klass);
411 }
412 #endif /* XMLSEC_NO_MD5 */
413
414 #ifndef XMLSEC_NO_SHA1
415 /******************************************************************************
416 *
417 * SHA1
418 *
419 *****************************************************************************/
420 static xmlSecTransformKlass xmlSecMSCngSha1Klass = {
421 /* klass/object sizes */
422 sizeof(xmlSecTransformKlass), /* size_t klassSize */
423 xmlSecMSCngDigestSize, /* size_t objSize */
424
425 xmlSecNameSha1, /* const xmlChar* name; */
426 xmlSecHrefSha1, /* const xmlChar* href; */
427 xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
428 xmlSecMSCngDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
429 xmlSecMSCngDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
430 NULL, /* xmlSecTransformNodeReadMethod readNode; */
431 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
432 NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
433 NULL, /* xmlSecTransformSetKeyMethod setKey; */
434 xmlSecMSCngDigestVerify, /* xmlSecTransformVerifyMethod verify; */
435 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
436 xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
437 xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
438 NULL, /* xmlSecTransformPushXmlMethod pushXml; */
439 NULL, /* xmlSecTransformPopXmlMethod popXml; */
440 xmlSecMSCngDigestExecute, /* xmlSecTransformExecuteMethod execute; */
441 NULL, /* void* reserved0; */
442 NULL, /* void* reserved1; */
443 };
444
445 /**
446 * xmlSecMSCngTransformSha1GetKlass:
447 *
448 * SHA-1 digest transform klass.
449 *
450 * Returns: pointer to SHA-1 digest transform klass.
451 */
452 xmlSecTransformId
xmlSecMSCngTransformSha1GetKlass(void)453 xmlSecMSCngTransformSha1GetKlass(void) {
454 return(&xmlSecMSCngSha1Klass);
455 }
456 #endif /* XMLSEC_NO_SHA1 */
457
458 #ifndef XMLSEC_NO_SHA256
459 /******************************************************************************
460 *
461 * SHA256
462 *
463 *****************************************************************************/
464 static xmlSecTransformKlass xmlSecMSCngSha256Klass = {
465 /* klass/object sizes */
466 sizeof(xmlSecTransformKlass), /* size_t klassSize */
467 xmlSecMSCngDigestSize, /* size_t objSize */
468
469 xmlSecNameSha256, /* const xmlChar* name; */
470 xmlSecHrefSha256, /* const xmlChar* href; */
471 xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
472 xmlSecMSCngDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
473 xmlSecMSCngDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
474 NULL, /* xmlSecTransformNodeReadMethod readNode; */
475 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
476 NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
477 NULL, /* xmlSecTransformSetKeyMethod setKey; */
478 xmlSecMSCngDigestVerify, /* xmlSecTransformVerifyMethod verify; */
479 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
480 xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
481 xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
482 NULL, /* xmlSecTransformPushXmlMethod pushXml; */
483 NULL, /* xmlSecTransformPopXmlMethod popXml; */
484 xmlSecMSCngDigestExecute, /* xmlSecTransformExecuteMethod execute; */
485 NULL, /* void* reserved0; */
486 NULL, /* void* reserved1; */
487 };
488
489 /**
490 * xmlSecMSCngTransformSha256GetKlass:
491 *
492 * SHA-256 digest transform klass.
493 *
494 * Returns: pointer to SHA-256 digest transform klass.
495 */
496 xmlSecTransformId
xmlSecMSCngTransformSha256GetKlass(void)497 xmlSecMSCngTransformSha256GetKlass(void) {
498 return(&xmlSecMSCngSha256Klass);
499 }
500 #endif /* XMLSEC_NO_SHA256 */
501
502 #ifndef XMLSEC_NO_SHA384
503 /******************************************************************************
504 *
505 * SHA384
506 *
507 *****************************************************************************/
508 static xmlSecTransformKlass xmlSecMSCngSha384Klass = {
509 /* klass/object sizes */
510 sizeof(xmlSecTransformKlass), /* size_t klassSize */
511 xmlSecMSCngDigestSize, /* size_t objSize */
512
513 xmlSecNameSha384, /* const xmlChar* name; */
514 xmlSecHrefSha384, /* const xmlChar* href; */
515 xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
516 xmlSecMSCngDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
517 xmlSecMSCngDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
518 NULL, /* xmlSecTransformNodeReadMethod readNode; */
519 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
520 NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
521 NULL, /* xmlSecTransformSetKeyMethod setKey; */
522 xmlSecMSCngDigestVerify, /* xmlSecTransformVerifyMethod verify; */
523 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
524 xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
525 xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
526 NULL, /* xmlSecTransformPushXmlMethod pushXml; */
527 NULL, /* xmlSecTransformPopXmlMethod popXml; */
528 xmlSecMSCngDigestExecute, /* xmlSecTransformExecuteMethod execute; */
529 NULL, /* void* reserved0; */
530 NULL, /* void* reserved1; */
531 };
532
533 /**
534 * xmlSecMSCngTransformSha384GetKlass:
535 *
536 * SHA-256 digest transform klass.
537 *
538 * Returns: pointer to SHA-256 digest transform klass.
539 */
540 xmlSecTransformId
xmlSecMSCngTransformSha384GetKlass(void)541 xmlSecMSCngTransformSha384GetKlass(void) {
542 return(&xmlSecMSCngSha384Klass);
543 }
544 #endif /* XMLSEC_NO_SHA384 */
545
546 #ifndef XMLSEC_NO_SHA512
547 /******************************************************************************
548 *
549 * SHA512
550 *
551 *****************************************************************************/
552 static xmlSecTransformKlass xmlSecMSCngSha512Klass = {
553 /* klass/object sizes */
554 sizeof(xmlSecTransformKlass), /* size_t klassSize */
555 xmlSecMSCngDigestSize, /* size_t objSize */
556
557 xmlSecNameSha512, /* const xmlChar* name; */
558 xmlSecHrefSha512, /* const xmlChar* href; */
559 xmlSecTransformUsageDigestMethod, /* xmlSecTransformUsage usage; */
560 xmlSecMSCngDigestInitialize, /* xmlSecTransformInitializeMethod initialize; */
561 xmlSecMSCngDigestFinalize, /* xmlSecTransformFinalizeMethod finalize; */
562 NULL, /* xmlSecTransformNodeReadMethod readNode; */
563 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
564 NULL, /* xmlSecTransformSetKeyReqMethod setKeyReq; */
565 NULL, /* xmlSecTransformSetKeyMethod setKey; */
566 xmlSecMSCngDigestVerify, /* xmlSecTransformVerifyMethod verify; */
567 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
568 xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
569 xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
570 NULL, /* xmlSecTransformPushXmlMethod pushXml; */
571 NULL, /* xmlSecTransformPopXmlMethod popXml; */
572 xmlSecMSCngDigestExecute, /* xmlSecTransformExecuteMethod execute; */
573 NULL, /* void* reserved0; */
574 NULL, /* void* reserved1; */
575 };
576
577 /**
578 * xmlSecMSCngTransformSha512GetKlass:
579 *
580 * SHA-512 digest transform klass.
581 *
582 * Returns: pointer to SHA-512 digest transform klass.
583 */
584 xmlSecTransformId
xmlSecMSCngTransformSha512GetKlass(void)585 xmlSecMSCngTransformSha512GetKlass(void) {
586 return(&xmlSecMSCngSha512Klass);
587 }
588 #endif /* XMLSEC_NO_SHA512 */
589