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