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