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) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
9  */
10 /**
11  * SECTION:hmac
12  * @Short_description: HMAC transforms implementation for Microsoft Crypto API.
13  * @Stability: Private
14  *
15  * [HMAC Algorithm support](http://www.w3.org/TR/xmldsig-core/#sec-HMAC):
16  * The HMAC algorithm (RFC2104 [HMAC]) takes the truncation length in bits
17  * as a parameter; if the parameter is not specified then all the bits of the
18  * hash are output. An example of an HMAC SignatureMethod element:
19  *
20  * |[<!-- language="XML" -->
21  * <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1">
22  *   <HMACOutputLength>128</HMACOutputLength>
23  * </SignatureMethod>
24  * |]
25  */
26 
27 
28 #ifndef XMLSEC_NO_HMAC
29 #include "globals.h"
30 
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <windows.h>
35 #include <wincrypt.h>
36 
37 #include <xmlsec/xmlsec.h>
38 #include <xmlsec/xmltree.h>
39 #include <xmlsec/base64.h>
40 #include <xmlsec/keys.h>
41 #include <xmlsec/transforms.h>
42 #include <xmlsec/errors.h>
43 
44 #include <xmlsec/mscrypto/crypto.h>
45 #include "private.h"
46 
47 /* sizes in bits */
48 #define XMLSEC_MSCRYPTO_MIN_HMAC_SIZE            80
49 #define XMLSEC_MSCRYPTO_MAX_HMAC_SIZE            256
50 
51 /**************************************************************************
52  *
53  * Configuration
54  *
55  *****************************************************************************/
56 static int g_xmlsec_mscrypto_hmac_min_length = XMLSEC_MSCRYPTO_MIN_HMAC_SIZE;
57 
58 /**
59  * xmlSecMSCryptoHmacGetMinOutputLength:
60  *
61  * Gets the value of min HMAC length.
62  *
63  * Returns: the min HMAC output length
64  */
xmlSecMSCryptoHmacGetMinOutputLength(void)65 int xmlSecMSCryptoHmacGetMinOutputLength(void)
66 {
67     return g_xmlsec_mscrypto_hmac_min_length;
68 }
69 
70 /**
71  * xmlSecMSCryptoHmacSetMinOutputLength:
72  * @min_length: the new min length
73  *
74  * Sets the min HMAC output length
75  */
xmlSecMSCryptoHmacSetMinOutputLength(int min_length)76 void xmlSecMSCryptoHmacSetMinOutputLength(int min_length)
77 {
78     g_xmlsec_mscrypto_hmac_min_length = min_length;
79 }
80 
81 /******************************************************************************
82  *
83  * Internal MSCrypto HMAC CTX
84  *
85  *****************************************************************************/
86 typedef struct _xmlSecMSCryptoHmacCtx            xmlSecMSCryptoHmacCtx, *xmlSecMSCryptoHmacCtxPtr;
87 struct _xmlSecMSCryptoHmacCtx {
88     HCRYPTPROV      provider;
89     HCRYPTKEY       cryptKey;
90     HCRYPTKEY       pubPrivKey;
91     ALG_ID          alg_id;
92     const xmlSecMSCryptoProviderInfo  * providers;
93     HCRYPTHASH      mscHash;
94     unsigned char   dgst[XMLSEC_MSCRYPTO_MAX_HMAC_SIZE];
95     xmlSecSize      dgstSize;   /* dgst size in bytes */
96     int             ctxInitialized;
97 };
98 
99 /******************************************************************************
100  *
101  * HMAC transforms
102  *
103  * xmlSecMSCryptoHmacCtx is located after xmlSecTransform
104  *
105  *****************************************************************************/
106 #define xmlSecMSCryptoHmacGetCtx(transform) \
107     ((xmlSecMSCryptoHmacCtxPtr)(((xmlSecByte*)(transform)) + sizeof(xmlSecTransform)))
108 #define xmlSecMSCryptoHmacSize   \
109     (sizeof(xmlSecTransform) + sizeof(xmlSecMSCryptoHmacCtx))
110 
111 static int      xmlSecMSCryptoHmacCheckId                        (xmlSecTransformPtr transform);
112 static int      xmlSecMSCryptoHmacInitialize                     (xmlSecTransformPtr transform);
113 static void     xmlSecMSCryptoHmacFinalize                       (xmlSecTransformPtr transform);
114 static int      xmlSecMSCryptoHmacNodeRead                       (xmlSecTransformPtr transform,
115                                                                  xmlNodePtr node,
116                                                                  xmlSecTransformCtxPtr transformCtx);
117 static int      xmlSecMSCryptoHmacSetKeyReq                      (xmlSecTransformPtr transform,
118                                                                  xmlSecKeyReqPtr keyReq);
119 static int      xmlSecMSCryptoHmacSetKey                         (xmlSecTransformPtr transform,
120                                                                  xmlSecKeyPtr key);
121 static int      xmlSecMSCryptoHmacVerify                         (xmlSecTransformPtr transform,
122                                                                  const xmlSecByte* data,
123                                                                  xmlSecSize dataSize,
124                                                                  xmlSecTransformCtxPtr transformCtx);
125 static int      xmlSecMSCryptoHmacExecute                        (xmlSecTransformPtr transform,
126                                                                  int last,
127                                                                  xmlSecTransformCtxPtr transformCtx);
128 
129 /* Ordered list of providers to search for algorithm implementation using
130  * xmlSecMSCryptoFindProvider() function
131  *
132  * MUST END with { NULL, 0 } !!!
133  */
134 static xmlSecMSCryptoProviderInfo xmlSecMSCryptoProviderInfo_Hmac[] = {
135     { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV,                PROV_RSA_AES},
136     { XMLSEC_CRYPTO_MS_ENH_RSA_AES_PROV_PROTOTYPE,      PROV_RSA_AES },
137     { MS_STRONG_PROV,                                   PROV_RSA_FULL },
138     { MS_ENHANCED_PROV,                                 PROV_RSA_FULL },
139     { MS_DEF_PROV,                                      PROV_RSA_FULL },
140     { NULL, 0 }
141 };
142 
143 static int
xmlSecMSCryptoHmacCheckId(xmlSecTransformPtr transform)144 xmlSecMSCryptoHmacCheckId(xmlSecTransformPtr transform) {
145 
146 #ifndef XMLSEC_NO_SHA1
147     if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformHmacSha1Id)) {
148         return(1);
149     } else
150 #endif /* XMLSEC_NO_SHA1 */
151 
152 #ifndef XMLSEC_NO_SHA256
153     if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformHmacSha256Id)) {
154         return(1);
155     } else
156 #endif /* XMLSEC_NO_SHA256 */
157 
158 #ifndef XMLSEC_NO_SHA384
159     if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformHmacSha384Id)) {
160         return(1);
161     } else
162 #endif /* XMLSEC_NO_SHA384 */
163 
164 #ifndef XMLSEC_NO_SHA512
165     if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformHmacSha512Id)) {
166         return(1);
167     } else
168 #endif /* XMLSEC_NO_SHA512 */
169 
170 #ifndef XMLSEC_NO_MD5
171     if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformHmacMd5Id)) {
172         return(1);
173     } else
174 #endif /* XMLSEC_NO_MD5 */
175 
176     /* not found */
177     {
178         return(0);
179     }
180 }
181 
182 static int
xmlSecMSCryptoHmacInitialize(xmlSecTransformPtr transform)183 xmlSecMSCryptoHmacInitialize(xmlSecTransformPtr transform) {
184     xmlSecMSCryptoHmacCtxPtr ctx;
185 
186     xmlSecAssert2(xmlSecMSCryptoHmacCheckId(transform), -1);
187     xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoHmacSize), -1);
188 
189     ctx = xmlSecMSCryptoHmacGetCtx(transform);
190     xmlSecAssert2(ctx != NULL, -1);
191 
192     /* initialize context */
193     memset(ctx, 0, sizeof(xmlSecMSCryptoHmacCtx));
194 
195 #ifndef XMLSEC_NO_SHA1
196     if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformHmacSha1Id)) {
197         ctx->alg_id = CALG_SHA1;
198         ctx->providers = xmlSecMSCryptoProviderInfo_Hmac;
199     } else
200 #endif /* XMLSEC_NO_SHA1 */
201 
202 #ifndef XMLSEC_NO_SHA256
203     if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformHmacSha256Id)) {
204         ctx->alg_id = CALG_SHA_256;
205         ctx->providers = xmlSecMSCryptoProviderInfo_Hmac;
206     } else
207 #endif /* XMLSEC_NO_SHA256 */
208 
209 #ifndef XMLSEC_NO_SHA384
210     if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformHmacSha384Id)) {
211         ctx->alg_id = CALG_SHA_384;
212         ctx->providers = xmlSecMSCryptoProviderInfo_Hmac;
213     } else
214 #endif /* XMLSEC_NO_SHA384 */
215 
216 #ifndef XMLSEC_NO_SHA512
217     if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformHmacSha512Id)) {
218         ctx->alg_id = CALG_SHA_512;
219         ctx->providers = xmlSecMSCryptoProviderInfo_Hmac;
220     } else
221 #endif /* XMLSEC_NO_SHA512 */
222 
223 #ifndef XMLSEC_NO_MD5
224     if(xmlSecTransformCheckId(transform, xmlSecMSCryptoTransformHmacMd5Id)) {
225         ctx->alg_id = CALG_MD5;
226         ctx->providers = xmlSecMSCryptoProviderInfo_Hmac;
227     } else
228 #endif /* XMLSEC_NO_MD5 */
229 
230     /* not found */
231     {
232         xmlSecInvalidTransfromError(transform)
233         return(-1);
234     }
235 
236     ctx->provider = xmlSecMSCryptoFindProvider(ctx->providers, NULL, CRYPT_VERIFYCONTEXT, TRUE);
237     if(ctx->provider == 0) {
238         xmlSecInternalError("xmlSecMSCryptoFindProvider",
239                             xmlSecTransformGetName(transform));
240         return(-1);
241     }
242 
243     /* Create dummy key to be able to import plain session keys */
244     if (!xmlSecMSCryptoCreatePrivateExponentOneKey(ctx->provider, &(ctx->pubPrivKey))) {
245         xmlSecMSCryptoError("xmlSecMSCryptoCreatePrivateExponentOneKey",
246                             xmlSecTransformGetName(transform));
247 
248         return(-1);
249     }
250 
251     return(0);
252 }
253 
254 static void
xmlSecMSCryptoHmacFinalize(xmlSecTransformPtr transform)255 xmlSecMSCryptoHmacFinalize(xmlSecTransformPtr transform) {
256     xmlSecMSCryptoHmacCtxPtr ctx;
257 
258     xmlSecAssert(xmlSecMSCryptoHmacCheckId(transform));
259     xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecMSCryptoHmacSize));
260 
261     ctx = xmlSecMSCryptoHmacGetCtx(transform);
262     xmlSecAssert(ctx != NULL);
263 
264     if(ctx->mscHash != 0) {
265         CryptDestroyHash(ctx->mscHash);
266     }
267     if (ctx->cryptKey) {
268         CryptDestroyKey(ctx->cryptKey);
269     }
270     if (ctx->pubPrivKey) {
271         CryptDestroyKey(ctx->pubPrivKey);
272     }
273     if(ctx->provider != 0) {
274         CryptReleaseContext(ctx->provider, 0);
275     }
276 
277     memset(ctx, 0, sizeof(xmlSecMSCryptoHmacCtx));
278 }
279 
280 static int
xmlSecMSCryptoHmacNodeRead(xmlSecTransformPtr transform,xmlNodePtr node,xmlSecTransformCtxPtr transformCtx)281 xmlSecMSCryptoHmacNodeRead(xmlSecTransformPtr transform, xmlNodePtr node, xmlSecTransformCtxPtr transformCtx) {
282     xmlSecMSCryptoHmacCtxPtr ctx;
283     xmlNodePtr cur;
284 
285     xmlSecAssert2(xmlSecMSCryptoHmacCheckId(transform), -1);
286     xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoHmacSize), -1);
287     xmlSecAssert2(node!= NULL, -1);
288     xmlSecAssert2(transformCtx != NULL, -1);
289 
290     ctx = xmlSecMSCryptoHmacGetCtx(transform);
291     xmlSecAssert2(ctx != NULL, -1);
292 
293     cur = xmlSecGetNextElementNode(node->children);
294     if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeHMACOutputLength, xmlSecDSigNs)) {
295         xmlChar *content;
296 
297         content = xmlNodeGetContent(cur);
298         if(content != NULL) {
299             ctx->dgstSize = atoi((char*)content);
300             xmlFree(content);
301         }
302 
303         /* Ensure that HMAC length is greater than min specified.
304            Otherwise, an attacker can set this length to 0 or very
305            small value
306         */
307         if((int)ctx->dgstSize < xmlSecMSCryptoHmacGetMinOutputLength()) {
308             xmlSecInvalidNodeContentError(cur, xmlSecTransformGetName(transform),
309                                           "HMAC output length is too small");
310             return(-1);
311         }
312 
313         cur = xmlSecGetNextElementNode(cur->next);
314     }
315 
316     if(cur != NULL) {
317         xmlSecUnexpectedNodeError(cur, xmlSecTransformGetName(transform));
318         return(-1);
319     }
320     return(0);
321 }
322 
323 static int
xmlSecMSCryptoHmacSetKeyReq(xmlSecTransformPtr transform,xmlSecKeyReqPtr keyReq)324 xmlSecMSCryptoHmacSetKeyReq(xmlSecTransformPtr transform,  xmlSecKeyReqPtr keyReq) {
325     xmlSecAssert2(xmlSecMSCryptoHmacCheckId(transform), -1);
326     xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
327     xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoHmacSize), -1);
328     xmlSecAssert2(keyReq != NULL, -1);
329 
330     keyReq->keyId   = xmlSecMSCryptoKeyDataHmacId;
331     keyReq->keyType = xmlSecKeyDataTypeSymmetric;
332     if(transform->operation == xmlSecTransformOperationSign) {
333         keyReq->keyUsage = xmlSecKeyUsageSign;
334     } else {
335         keyReq->keyUsage = xmlSecKeyUsageVerify;
336     }
337 
338     return(0);
339 }
340 
341 static int
xmlSecMSCryptoHmacSetKey(xmlSecTransformPtr transform,xmlSecKeyPtr key)342 xmlSecMSCryptoHmacSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
343     xmlSecMSCryptoHmacCtxPtr ctx;
344     xmlSecKeyDataPtr value;
345     xmlSecBufferPtr buffer;
346     HMAC_INFO hmacInfo;
347     int ret;
348 
349     xmlSecAssert2(xmlSecMSCryptoHmacCheckId(transform), -1);
350     xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
351     xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoHmacSize), -1);
352     xmlSecAssert2(key != NULL, -1);
353 
354     ctx = xmlSecMSCryptoHmacGetCtx(transform);
355     xmlSecAssert2(ctx != NULL, -1);
356     xmlSecAssert2(ctx->ctxInitialized == 0, -1);
357     xmlSecAssert2(ctx->provider != 0, -1);
358     xmlSecAssert2(ctx->pubPrivKey != 0, -1);
359     xmlSecAssert2(ctx->cryptKey == 0, -1);
360     xmlSecAssert2(ctx->mscHash == 0, -1);
361 
362     value = xmlSecKeyGetValue(key);
363     xmlSecAssert2(xmlSecKeyDataCheckId(value, xmlSecMSCryptoKeyDataHmacId), -1);
364 
365     buffer = xmlSecKeyDataBinaryValueGetBuffer(value);
366     xmlSecAssert2(buffer != NULL, -1);
367 
368     if(xmlSecBufferGetSize(buffer) == 0) {
369         xmlSecInvalidZeroKeyDataSizeError(xmlSecTransformGetName(transform));
370         return(-1);
371     }
372 
373     xmlSecAssert2(xmlSecBufferGetData(buffer) != NULL, -1);
374 
375     /* Import this key and get an HCRYPTKEY handle.
376      *
377      * HACK!!! HACK!!! HACK!!!
378      *
379      * Using CALG_RC2 instead of CALG_HMAC for the key algorithm so we don't want to check key length
380      */
381     if (!xmlSecMSCryptoImportPlainSessionBlob(ctx->provider,
382         ctx->pubPrivKey,
383         CALG_RC2,
384         xmlSecBufferGetData(buffer),
385         xmlSecBufferGetSize(buffer),
386         FALSE,
387         &(ctx->cryptKey)
388         ) || (ctx->cryptKey == 0))  {
389 
390         xmlSecInternalError("xmlSecMSCryptoImportPlainSessionBlob",
391                             xmlSecTransformGetName(transform));
392         return(-1);
393     }
394 
395     /* create hash */
396     ret = CryptCreateHash(ctx->provider,
397         CALG_HMAC,
398         ctx->cryptKey,
399         0,
400         &(ctx->mscHash));
401     if((ret == 0) || (ctx->mscHash == 0)) {
402         xmlSecMSCryptoError("CryptCreateHash",
403                             xmlSecTransformGetName(transform));
404         return(-1);
405     }
406 
407     /* set parameters */
408     memset(&hmacInfo, 0, sizeof(hmacInfo));
409     hmacInfo.HashAlgid = ctx->alg_id;
410     ret = CryptSetHashParam(ctx->mscHash, HP_HMAC_INFO, (BYTE*)&hmacInfo, 0);
411     if(ret == 0) {
412         xmlSecMSCryptoError("CryptSetHashParam",
413                             xmlSecTransformGetName(transform));
414         return(-1);
415     }
416 
417     /* done */
418     ctx->ctxInitialized = 1;
419     return(0);
420 }
421 
422 static int
xmlSecMSCryptoHmacVerify(xmlSecTransformPtr transform,const xmlSecByte * data,xmlSecSize dataSize,xmlSecTransformCtxPtr transformCtx)423 xmlSecMSCryptoHmacVerify(xmlSecTransformPtr transform,
424                         const xmlSecByte* data, xmlSecSize dataSize,
425                         xmlSecTransformCtxPtr transformCtx) {
426     static xmlSecByte last_byte_masks[] =
427                 { 0xFF, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
428 
429     xmlSecMSCryptoHmacCtxPtr ctx;
430     xmlSecByte mask;
431 
432     xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
433     xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoHmacSize), -1);
434     xmlSecAssert2(transform->operation == xmlSecTransformOperationVerify, -1);
435     xmlSecAssert2(transform->status == xmlSecTransformStatusFinished, -1);
436     xmlSecAssert2(data != NULL, -1);
437     xmlSecAssert2(transformCtx != NULL, -1);
438 
439     ctx = xmlSecMSCryptoHmacGetCtx(transform);
440     xmlSecAssert2(ctx != NULL, -1);
441     xmlSecAssert2(ctx->dgstSize > 0, -1);
442 
443     /* compare the digest size in bytes */
444     if(dataSize != ((ctx->dgstSize + 7) / 8)){
445         xmlSecInvalidSizeError("HMAC digest",
446                                dataSize, ((ctx->dgstSize + 7) / 8),
447                                xmlSecTransformGetName(transform));
448         transform->status = xmlSecTransformStatusFail;
449         return(0);
450     }
451 
452     /* we check the last byte separately */
453     xmlSecAssert2(dataSize > 0, -1);
454     mask = last_byte_masks[ctx->dgstSize % 8];
455     if((ctx->dgst[dataSize - 1] & mask) != (data[dataSize - 1]  & mask)) {
456         xmlSecOtherError(XMLSEC_ERRORS_R_DATA_NOT_MATCH,
457                          xmlSecTransformGetName(transform),
458                          "data and digest do not match (last byte)");
459         transform->status = xmlSecTransformStatusFail;
460         return(0);
461     }
462 
463     /* now check the rest of the digest */
464     if((dataSize > 1) && (memcmp(ctx->dgst, data, dataSize - 1) != 0)) {
465         xmlSecOtherError(XMLSEC_ERRORS_R_DATA_NOT_MATCH,
466                          xmlSecTransformGetName(transform),
467                          "data and digest do not match");
468         transform->status = xmlSecTransformStatusFail;
469         return(0);
470     }
471 
472     transform->status = xmlSecTransformStatusOk;
473     return(0);
474 }
475 
476 static int
xmlSecMSCryptoHmacExecute(xmlSecTransformPtr transform,int last,xmlSecTransformCtxPtr transformCtx)477 xmlSecMSCryptoHmacExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) {
478     xmlSecMSCryptoHmacCtxPtr ctx;
479     xmlSecBufferPtr in, out;
480     int ret;
481 
482     xmlSecAssert2(xmlSecTransformIsValid(transform), -1);
483     xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1);
484     xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCryptoHmacSize), -1);
485     xmlSecAssert2(transformCtx != NULL, -1);
486 
487     in = &(transform->inBuf);
488     out = &(transform->outBuf);
489 
490     ctx = xmlSecMSCryptoHmacGetCtx(transform);
491     xmlSecAssert2(ctx != NULL, -1);
492     xmlSecAssert2(ctx->ctxInitialized != 0, -1);
493 
494     if(transform->status == xmlSecTransformStatusNone) {
495         /* we should be already initialized when we set key */
496         transform->status = xmlSecTransformStatusWorking;
497     }
498 
499     if(transform->status == xmlSecTransformStatusWorking) {
500         xmlSecSize inSize;
501 
502         inSize = xmlSecBufferGetSize(in);
503         if(inSize > 0) {
504             ret = CryptHashData(ctx->mscHash,
505                 xmlSecBufferGetData(in),
506                 inSize,
507                 0);
508 
509             if(ret == 0) {
510                 xmlSecMSCryptoError2("CryptHashData",
511                                     xmlSecTransformGetName(transform),
512                                     "size=%d", inSize);
513                 return(-1);
514             }
515 
516             ret = xmlSecBufferRemoveHead(in, inSize);
517             if(ret < 0) {
518                 xmlSecInternalError2("xmlSecBufferRemoveHead",
519                                      xmlSecTransformGetName(transform),
520                                      "size=%d", inSize);
521                 return(-1);
522             }
523         }
524 
525         if(last) {
526             /* TODO: make a MSCrypto compatible assert here */
527             /* xmlSecAssert2((xmlSecSize)EVP_MD_size(ctx->digest) <= sizeof(ctx->dgst), -1); */
528             DWORD retLen;
529             retLen = XMLSEC_MSCRYPTO_MAX_HMAC_SIZE;
530 
531             ret = CryptGetHashParam(ctx->mscHash,
532                 HP_HASHVAL,
533                 ctx->dgst,
534                 &retLen,
535                 0);
536 
537             if (ret == 0) {
538                 xmlSecInternalError2("CryptGetHashParam",
539                                      xmlSecTransformGetName(transform),
540                                      "size=%d", inSize);
541                 return(-1);
542             }
543             xmlSecAssert2(retLen > 0, -1);
544 
545             /* check/set the result digest size */
546             if(ctx->dgstSize == 0) {
547                 ctx->dgstSize = retLen * 8; /* no dgst size specified, use all we have */
548             } else if(ctx->dgstSize <= 8 * retLen) {
549                 retLen = ((ctx->dgstSize + 7) / 8); /* we need to truncate result digest */
550             } else {
551                 xmlSecInvalidSizeLessThanError("HMAC digest (bits)",
552                                         8 * retLen, ctx->dgstSize,
553                                         xmlSecTransformGetName(transform));
554                 return(-1);
555             }
556 
557             /* copy result to output */
558             if(transform->operation == xmlSecTransformOperationSign) {
559                 ret = xmlSecBufferAppend(out, ctx->dgst, retLen);
560                 if(ret < 0) {
561                     xmlSecInternalError2("xmlSecBufferAppend",
562                                          xmlSecTransformGetName(transform),
563                                          "size=%d", ctx->dgstSize);
564                     return(-1);
565                 }
566             }
567             transform->status = xmlSecTransformStatusFinished;
568         }
569     } else if(transform->status == xmlSecTransformStatusFinished) {
570         /* the only way we can get here is if there is no input */
571         xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1);
572     } else {
573         xmlSecInvalidTransfromStatusError(transform);
574         return(-1);
575     }
576 
577     return(0);
578 }
579 
580 #ifndef XMLSEC_NO_MD5
581 /******************************************************************************
582  *
583  * HMAC MD5
584  *
585  ******************************************************************************/
586 static xmlSecTransformKlass xmlSecMSCryptoHmacMd5Klass = {
587     /* klass/object sizes */
588     sizeof(xmlSecTransformKlass),               /* xmlSecSize klassSize */
589     xmlSecMSCryptoHmacSize,                      /* xmlSecSize objSize */
590 
591     xmlSecNameHmacMd5,                          /* const xmlChar* name; */
592     xmlSecHrefHmacMd5,                          /* const xmlChar* href; */
593     xmlSecTransformUsageSignatureMethod,        /* xmlSecTransformUsage usage; */
594 
595     xmlSecMSCryptoHmacInitialize,                /* xmlSecTransformInitializeMethod initialize; */
596     xmlSecMSCryptoHmacFinalize,                  /* xmlSecTransformFinalizeMethod finalize; */
597     xmlSecMSCryptoHmacNodeRead,                  /* xmlSecTransformNodeReadMethod readNode; */
598     NULL,                                       /* xmlSecTransformNodeWriteMethod writeNode; */
599     xmlSecMSCryptoHmacSetKeyReq,                 /* xmlSecTransformSetKeyReqMethod setKeyReq; */
600     xmlSecMSCryptoHmacSetKey,                    /* xmlSecTransformSetKeyMethod setKey; */
601     xmlSecMSCryptoHmacVerify,                    /* xmlSecTransformValidateMethod validate; */
602     xmlSecTransformDefaultGetDataType,          /* xmlSecTransformGetDataTypeMethod getDataType; */
603     xmlSecTransformDefaultPushBin,              /* xmlSecTransformPushBinMethod pushBin; */
604     xmlSecTransformDefaultPopBin,               /* xmlSecTransformPopBinMethod popBin; */
605     NULL,                                       /* xmlSecTransformPushXmlMethod pushXml; */
606     NULL,                                       /* xmlSecTransformPopXmlMethod popXml; */
607     xmlSecMSCryptoHmacExecute,                   /* xmlSecTransformExecuteMethod execute; */
608 
609     NULL,                                       /* void* reserved0; */
610     NULL,                                       /* void* reserved1; */
611 };
612 
613 /**
614  * xmlSecMSCryptoTransformHmacMd5GetKlass:
615  *
616  * The HMAC-MD5 transform klass.
617  *
618  * Returns: the HMAC-MD5 transform klass.
619  */
620 xmlSecTransformId
xmlSecMSCryptoTransformHmacMd5GetKlass(void)621 xmlSecMSCryptoTransformHmacMd5GetKlass(void) {
622     return(&xmlSecMSCryptoHmacMd5Klass);
623 }
624 
625 #endif /* XMLSEC_NO_MD5 */
626 
627 
628 #ifndef XMLSEC_NO_RIPEMD160
629 /******************************************************************************
630  *
631  * HMAC RIPEMD160
632  *
633  ******************************************************************************/
634 static xmlSecTransformKlass xmlSecMSCryptoHmacRipemd160Klass = {
635     /* klass/object sizes */
636     sizeof(xmlSecTransformKlass),               /* xmlSecSize klassSize */
637     xmlSecMSCryptoHmacSize,                      /* xmlSecSize objSize */
638 
639     xmlSecNameHmacRipemd160,                    /* const xmlChar* name; */
640     xmlSecHrefHmacRipemd160,                    /* const xmlChar* href; */
641     xmlSecTransformUsageSignatureMethod,        /* xmlSecTransformUsage usage; */
642 
643     xmlSecMSCryptoHmacInitialize,                /* xmlSecTransformInitializeMethod initialize; */
644     xmlSecMSCryptoHmacFinalize,                  /* xmlSecTransformFinalizeMethod finalize; */
645     xmlSecMSCryptoHmacNodeRead,                  /* xmlSecTransformNodeReadMethod readNode; */
646     NULL,                                       /* xmlSecTransformNodeWriteMethod writeNode; */
647     xmlSecMSCryptoHmacSetKeyReq,                 /* xmlSecTransformSetKeyReqMethod setKeyReq; */
648     xmlSecMSCryptoHmacSetKey,                    /* xmlSecTransformSetKeyMethod setKey; */
649     xmlSecMSCryptoHmacVerify,                    /* xmlSecTransformValidateMethod validate; */
650     xmlSecTransformDefaultGetDataType,          /* xmlSecTransformGetDataTypeMethod getDataType; */
651     xmlSecTransformDefaultPushBin,              /* xmlSecTransformPushBinMethod pushBin; */
652     xmlSecTransformDefaultPopBin,               /* xmlSecTransformPopBinMethod popBin; */
653     NULL,                                       /* xmlSecTransformPushXmlMethod pushXml; */
654     NULL,                                       /* xmlSecTransformPopXmlMethod popXml; */
655     xmlSecMSCryptoHmacExecute,                   /* xmlSecTransformExecuteMethod execute; */
656 
657     NULL,                                       /* void* reserved0; */
658     NULL,                                       /* void* reserved1; */
659 };
660 
661 /**
662  * xmlSecMSCryptoTransformHmacRipemd160GetKlass:
663  *
664  * The HMAC-RIPEMD160 transform klass.
665  *
666  * Returns: the HMAC-RIPEMD160 transform klass.
667  */
668 xmlSecTransformId
xmlSecMSCryptoTransformHmacRipemd160GetKlass(void)669 xmlSecMSCryptoTransformHmacRipemd160GetKlass(void) {
670     return(&xmlSecMSCryptoHmacRipemd160Klass);
671 }
672 #endif /* XMLSEC_NO_RIPEMD160 */
673 
674 #ifndef XMLSEC_NO_SHA1
675 /******************************************************************************
676  *
677  * HMAC SHA1
678  *
679  ******************************************************************************/
680 static xmlSecTransformKlass xmlSecMSCryptoHmacSha1Klass = {
681     /* klass/object sizes */
682     sizeof(xmlSecTransformKlass),               /* xmlSecSize klassSize */
683     xmlSecMSCryptoHmacSize,                      /* xmlSecSize objSize */
684 
685     xmlSecNameHmacSha1,                         /* const xmlChar* name; */
686     xmlSecHrefHmacSha1,                         /* const xmlChar* href; */
687     xmlSecTransformUsageSignatureMethod,        /* xmlSecTransformUsage usage; */
688 
689     xmlSecMSCryptoHmacInitialize,                /* xmlSecTransformInitializeMethod initialize; */
690     xmlSecMSCryptoHmacFinalize,                  /* xmlSecTransformFinalizeMethod finalize; */
691     xmlSecMSCryptoHmacNodeRead,                  /* xmlSecTransformNodeReadMethod readNode; */
692     NULL,                                       /* xmlSecTransformNodeWriteMethod writeNode; */
693     xmlSecMSCryptoHmacSetKeyReq,                 /* xmlSecTransformSetKeyReqMethod setKeyReq; */
694     xmlSecMSCryptoHmacSetKey,                    /* xmlSecTransformSetKeyMethod setKey; */
695     xmlSecMSCryptoHmacVerify,                    /* xmlSecTransformValidateMethod validate; */
696     xmlSecTransformDefaultGetDataType,          /* xmlSecTransformGetDataTypeMethod getDataType; */
697     xmlSecTransformDefaultPushBin,              /* xmlSecTransformPushBinMethod pushBin; */
698     xmlSecTransformDefaultPopBin,               /* xmlSecTransformPopBinMethod popBin; */
699     NULL,                                       /* xmlSecTransformPushXmlMethod pushXml; */
700     NULL,                                       /* xmlSecTransformPopXmlMethod popXml; */
701     xmlSecMSCryptoHmacExecute,                   /* xmlSecTransformExecuteMethod execute; */
702 
703     NULL,                                       /* void* reserved0; */
704     NULL,                                       /* void* reserved1; */
705 };
706 
707 /**
708  * xmlSecMSCryptoTransformHmacSha1GetKlass:
709  *
710  * The HMAC-SHA1 transform klass.
711  *
712  * Returns: the HMAC-SHA1 transform klass.
713  */
714 xmlSecTransformId
xmlSecMSCryptoTransformHmacSha1GetKlass(void)715 xmlSecMSCryptoTransformHmacSha1GetKlass(void) {
716     return(&xmlSecMSCryptoHmacSha1Klass);
717 }
718 
719 #endif /* XMLSEC_NO_SHA1 */
720 
721 #ifndef XMLSEC_NO_SHA224
722 /******************************************************************************
723  *
724  * HMAC SHA224
725  *
726  ******************************************************************************/
727 static xmlSecTransformKlass xmlSecMSCryptoHmacSha224Klass = {
728     /* klass/object sizes */
729     sizeof(xmlSecTransformKlass),               /* xmlSecSize klassSize */
730     xmlSecMSCryptoHmacSize,                      /* xmlSecSize objSize */
731 
732     xmlSecNameHmacSha224,                       /* const xmlChar* name; */
733     xmlSecHrefHmacSha224,                       /* const xmlChar* href; */
734     xmlSecTransformUsageSignatureMethod,        /* xmlSecTransformUsage usage; */
735 
736     xmlSecMSCryptoHmacInitialize,                /* xmlSecTransformInitializeMethod initialize; */
737     xmlSecMSCryptoHmacFinalize,                  /* xmlSecTransformFinalizeMethod finalize; */
738     xmlSecMSCryptoHmacNodeRead,                  /* xmlSecTransformNodeReadMethod readNode; */
739     NULL,                                       /* xmlSecTransformNodeWriteMethod writeNode; */
740     xmlSecMSCryptoHmacSetKeyReq,                 /* xmlSecTransformSetKeyReqMethod setKeyReq; */
741     xmlSecMSCryptoHmacSetKey,                    /* xmlSecTransformSetKeyMethod setKey; */
742     xmlSecMSCryptoHmacVerify,                    /* xmlSecTransformValidateMethod validate; */
743     xmlSecTransformDefaultGetDataType,          /* xmlSecTransformGetDataTypeMethod getDataType; */
744     xmlSecTransformDefaultPushBin,              /* xmlSecTransformPushBinMethod pushBin; */
745     xmlSecTransformDefaultPopBin,               /* xmlSecTransformPopBinMethod popBin; */
746     NULL,                                       /* xmlSecTransformPushXmlMethod pushXml; */
747     NULL,                                       /* xmlSecTransformPopXmlMethod popXml; */
748     xmlSecMSCryptoHmacExecute,                   /* xmlSecTransformExecuteMethod execute; */
749 
750     NULL,                                       /* void* reserved0; */
751     NULL,                                       /* void* reserved1; */
752 };
753 
754 /**
755  * xmlSecMSCryptoTransformHmacSha224GetKlass:
756  *
757  * The HMAC-SHA224 transform klass.
758  *
759  * Returns: the HMAC-SHA224 transform klass.
760  */
761 xmlSecTransformId
xmlSecMSCryptoTransformHmacSha224GetKlass(void)762 xmlSecMSCryptoTransformHmacSha224GetKlass(void) {
763     return(&xmlSecMSCryptoHmacSha224Klass);
764 }
765 
766 #endif /* XMLSEC_NO_SHA224 */
767 
768 #ifndef XMLSEC_NO_SHA256
769 /******************************************************************************
770  *
771  * HMAC SHA256
772  *
773  ******************************************************************************/
774 static xmlSecTransformKlass xmlSecMSCryptoHmacSha256Klass = {
775     /* klass/object sizes */
776     sizeof(xmlSecTransformKlass),               /* xmlSecSize klassSize */
777     xmlSecMSCryptoHmacSize,                      /* xmlSecSize objSize */
778 
779     xmlSecNameHmacSha256,                       /* const xmlChar* name; */
780     xmlSecHrefHmacSha256,                       /* const xmlChar* href; */
781     xmlSecTransformUsageSignatureMethod,        /* xmlSecTransformUsage usage; */
782 
783     xmlSecMSCryptoHmacInitialize,                /* xmlSecTransformInitializeMethod initialize; */
784     xmlSecMSCryptoHmacFinalize,                  /* xmlSecTransformFinalizeMethod finalize; */
785     xmlSecMSCryptoHmacNodeRead,                  /* xmlSecTransformNodeReadMethod readNode; */
786     NULL,                                       /* xmlSecTransformNodeWriteMethod writeNode; */
787     xmlSecMSCryptoHmacSetKeyReq,                 /* xmlSecTransformSetKeyReqMethod setKeyReq; */
788     xmlSecMSCryptoHmacSetKey,                    /* xmlSecTransformSetKeyMethod setKey; */
789     xmlSecMSCryptoHmacVerify,                    /* xmlSecTransformValidateMethod validate; */
790     xmlSecTransformDefaultGetDataType,          /* xmlSecTransformGetDataTypeMethod getDataType; */
791     xmlSecTransformDefaultPushBin,              /* xmlSecTransformPushBinMethod pushBin; */
792     xmlSecTransformDefaultPopBin,               /* xmlSecTransformPopBinMethod popBin; */
793     NULL,                                       /* xmlSecTransformPushXmlMethod pushXml; */
794     NULL,                                       /* xmlSecTransformPopXmlMethod popXml; */
795     xmlSecMSCryptoHmacExecute,                   /* xmlSecTransformExecuteMethod execute; */
796 
797     NULL,                                       /* void* reserved0; */
798     NULL,                                       /* void* reserved1; */
799 };
800 
801 /**
802  * xmlSecMSCryptoTransformHmacSha256GetKlass:
803  *
804  * The HMAC-SHA256 transform klass.
805  *
806  * Returns: the HMAC-SHA256 transform klass.
807  */
808 xmlSecTransformId
xmlSecMSCryptoTransformHmacSha256GetKlass(void)809 xmlSecMSCryptoTransformHmacSha256GetKlass(void) {
810     return(&xmlSecMSCryptoHmacSha256Klass);
811 }
812 
813 #endif /* XMLSEC_NO_SHA256 */
814 
815 #ifndef XMLSEC_NO_SHA384
816 /******************************************************************************
817  *
818  * HMAC SHA384
819  *
820  ******************************************************************************/
821 static xmlSecTransformKlass xmlSecMSCryptoHmacSha384Klass = {
822     /* klass/object sizes */
823     sizeof(xmlSecTransformKlass),               /* xmlSecSize klassSize */
824     xmlSecMSCryptoHmacSize,                      /* xmlSecSize objSize */
825 
826     xmlSecNameHmacSha384,                       /* const xmlChar* name; */
827     xmlSecHrefHmacSha384,                       /* const xmlChar* href; */
828     xmlSecTransformUsageSignatureMethod,        /* xmlSecTransformUsage usage; */
829 
830     xmlSecMSCryptoHmacInitialize,                /* xmlSecTransformInitializeMethod initialize; */
831     xmlSecMSCryptoHmacFinalize,                  /* xmlSecTransformFinalizeMethod finalize; */
832     xmlSecMSCryptoHmacNodeRead,                  /* xmlSecTransformNodeReadMethod readNode; */
833     NULL,                                       /* xmlSecTransformNodeWriteMethod writeNode; */
834     xmlSecMSCryptoHmacSetKeyReq,                 /* xmlSecTransformSetKeyReqMethod setKeyReq; */
835     xmlSecMSCryptoHmacSetKey,                    /* xmlSecTransformSetKeyMethod setKey; */
836     xmlSecMSCryptoHmacVerify,                    /* xmlSecTransformValidateMethod validate; */
837     xmlSecTransformDefaultGetDataType,          /* xmlSecTransformGetDataTypeMethod getDataType; */
838     xmlSecTransformDefaultPushBin,              /* xmlSecTransformPushBinMethod pushBin; */
839     xmlSecTransformDefaultPopBin,               /* xmlSecTransformPopBinMethod popBin; */
840     NULL,                                       /* xmlSecTransformPushXmlMethod pushXml; */
841     NULL,                                       /* xmlSecTransformPopXmlMethod popXml; */
842     xmlSecMSCryptoHmacExecute,                   /* xmlSecTransformExecuteMethod execute; */
843 
844     NULL,                                       /* void* reserved0; */
845     NULL,                                       /* void* reserved1; */
846 };
847 
848 /**
849  * xmlSecMSCryptoTransformHmacSha384GetKlass:
850  *
851  * The HMAC-SHA384 transform klass.
852  *
853  * Returns: the HMAC-SHA384 transform klass.
854  */
855 xmlSecTransformId
xmlSecMSCryptoTransformHmacSha384GetKlass(void)856 xmlSecMSCryptoTransformHmacSha384GetKlass(void) {
857     return(&xmlSecMSCryptoHmacSha384Klass);
858 }
859 
860 #endif /* XMLSEC_NO_SHA384 */
861 
862 #ifndef XMLSEC_NO_SHA512
863 /******************************************************************************
864  *
865  * HMAC SHA512
866  *
867  ******************************************************************************/
868 static xmlSecTransformKlass xmlSecMSCryptoHmacSha512Klass = {
869     /* klass/object sizes */
870     sizeof(xmlSecTransformKlass),               /* xmlSecSize klassSize */
871     xmlSecMSCryptoHmacSize,                      /* xmlSecSize objSize */
872 
873     xmlSecNameHmacSha512,                       /* const xmlChar* name; */
874     xmlSecHrefHmacSha512,                       /* const xmlChar* href; */
875     xmlSecTransformUsageSignatureMethod,        /* xmlSecTransformUsage usage; */
876 
877     xmlSecMSCryptoHmacInitialize,                /* xmlSecTransformInitializeMethod initialize; */
878     xmlSecMSCryptoHmacFinalize,                  /* xmlSecTransformFinalizeMethod finalize; */
879     xmlSecMSCryptoHmacNodeRead,                  /* xmlSecTransformNodeReadMethod readNode; */
880     NULL,                                       /* xmlSecTransformNodeWriteMethod writeNode; */
881     xmlSecMSCryptoHmacSetKeyReq,                 /* xmlSecTransformSetKeyReqMethod setKeyReq; */
882     xmlSecMSCryptoHmacSetKey,                    /* xmlSecTransformSetKeyMethod setKey; */
883     xmlSecMSCryptoHmacVerify,                    /* xmlSecTransformValidateMethod validate; */
884     xmlSecTransformDefaultGetDataType,          /* xmlSecTransformGetDataTypeMethod getDataType; */
885     xmlSecTransformDefaultPushBin,              /* xmlSecTransformPushBinMethod pushBin; */
886     xmlSecTransformDefaultPopBin,               /* xmlSecTransformPopBinMethod popBin; */
887     NULL,                                       /* xmlSecTransformPushXmlMethod pushXml; */
888     NULL,                                       /* xmlSecTransformPopXmlMethod popXml; */
889     xmlSecMSCryptoHmacExecute,                   /* xmlSecTransformExecuteMethod execute; */
890 
891     NULL,                                       /* void* reserved0; */
892     NULL,                                       /* void* reserved1; */
893 };
894 
895 /**
896  * xmlSecMSCryptoTransformHmacSha512GetKlass:
897  *
898  * The HMAC-SHA512 transform klass.
899  *
900  * Returns: the HMAC-SHA512 transform klass.
901  */
902 xmlSecTransformId
xmlSecMSCryptoTransformHmacSha512GetKlass(void)903 xmlSecMSCryptoTransformHmacSha512GetKlass(void) {
904     return(&xmlSecMSCryptoHmacSha512Klass);
905 }
906 
907 #endif /* XMLSEC_NO_SHA512 */
908 
909 
910 #endif /* XMLSEC_NO_HMAC */
911 
912