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:ciphers
12 * @Short_description: Ciphers transforms implementation for Microsoft Cryptography API: Next Generation (CNG).
13 * @Stability: Private
14 *
15 */
16 #include "globals.h"
17
18 #include <string.h>
19
20 #define WIN32_NO_STATUS
21 #include <windows.h>
22 #undef WIN32_NO_STATUS
23 #include <ntstatus.h>
24 #include <bcrypt.h>
25 #include <ncrypt.h>
26
27 #include <xmlsec/xmlsec.h>
28 #include <xmlsec/xmltree.h>
29 #include <xmlsec/keys.h>
30 #include <xmlsec/keyinfo.h>
31 #include <xmlsec/transforms.h>
32 #include <xmlsec/errors.h>
33 #include <xmlsec/bn.h>
34
35 #include <xmlsec/mscng/crypto.h>
36
37 /**************************************************************************
38 *
39 * Internal MSCng Block cipher CTX
40 *
41 *****************************************************************************/
42 typedef struct _xmlSecMSCngBlockCipherCtx xmlSecMSCngBlockCipherCtx, *xmlSecMSCngBlockCipherCtxPtr;
43
44 struct _xmlSecMSCngBlockCipherCtx {
45 LPCWSTR pszAlgId;
46 BCRYPT_ALG_HANDLE hAlg;
47 BCRYPT_KEY_HANDLE hKey;
48 BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO authInfo;
49 PBYTE pbIV;
50 ULONG cbIV;
51 PBYTE pbKeyObject;
52 DWORD dwBlockLen;
53 xmlSecKeyDataId keyId;
54 xmlSecSize keySize;
55 int cbcMode;
56 int ctxInitialized;
57 };
58
59 #define xmlSecMSCngBlockCipherSize \
60 (sizeof(xmlSecTransform) + sizeof(xmlSecMSCngBlockCipherCtx))
61 #define xmlSecMSCngBlockCipherGetCtx(transform) \
62 ((xmlSecMSCngBlockCipherCtxPtr)(((unsigned char*)(transform)) + sizeof(xmlSecTransform)))
63
64 #define xmlSecMSCngAesGcmNonceLengthInBytes 12
65 #define xmlSecMSCngAesGcmTagLengthInBytes 16
66
67 static int
xmlSecMSCngBlockCipherCheckId(xmlSecTransformPtr transform)68 xmlSecMSCngBlockCipherCheckId(xmlSecTransformPtr transform) {
69 #ifndef XMLSEC_NO_AES
70 if(xmlSecTransformCheckId(transform, xmlSecMSCngTransformAes128CbcId)) {
71 return(1);
72 } else if(xmlSecTransformCheckId(transform, xmlSecMSCngTransformAes192CbcId)) {
73 return(1);
74 } else if(xmlSecTransformCheckId(transform, xmlSecMSCngTransformAes256CbcId)) {
75 return(1);
76 } else if(xmlSecTransformCheckId(transform, xmlSecMSCngTransformAes128GcmId)) {
77 return(1);
78 } else if(xmlSecTransformCheckId(transform, xmlSecMSCngTransformAes192GcmId)) {
79 return(1);
80 } else if(xmlSecTransformCheckId(transform, xmlSecMSCngTransformAes256GcmId)) {
81 return(1);
82 }
83 #endif /* XMLSEC_NO_AES */
84
85 #ifndef XMLSEC_NO_DES
86 if(xmlSecTransformCheckId(transform, xmlSecMSCngTransformDes3CbcId)) {
87 return(1);
88 }
89 #endif /* XMLSEC_NO_DES */
90
91 return(0);
92 }
93
94 static int
xmlSecMSCngBlockCipherInitialize(xmlSecTransformPtr transform)95 xmlSecMSCngBlockCipherInitialize(xmlSecTransformPtr transform) {
96 xmlSecMSCngBlockCipherCtxPtr ctx;
97 NTSTATUS status;
98
99 xmlSecAssert2(xmlSecMSCngBlockCipherCheckId(transform), -1);
100 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCngBlockCipherSize), -1);
101
102 ctx = xmlSecMSCngBlockCipherGetCtx(transform);
103 xmlSecAssert2(ctx != NULL, -1);
104
105 memset(ctx, 0, sizeof(xmlSecMSCngBlockCipherCtx));
106
107 #ifndef XMLSEC_NO_AES
108 if(transform->id == xmlSecMSCngTransformAes128CbcId) {
109 ctx->pszAlgId = BCRYPT_AES_ALGORITHM;
110 ctx->keyId = xmlSecMSCngKeyDataAesId;
111 ctx->keySize = 16;
112 ctx->cbcMode = 1;
113 } else if(transform->id == xmlSecMSCngTransformAes192CbcId) {
114 ctx->pszAlgId = BCRYPT_AES_ALGORITHM;
115 ctx->keyId = xmlSecMSCngKeyDataAesId;
116 ctx->keySize = 24;
117 ctx->cbcMode = 1;
118 } else if(transform->id == xmlSecMSCngTransformAes256CbcId) {
119 ctx->pszAlgId = BCRYPT_AES_ALGORITHM;
120 ctx->keyId = xmlSecMSCngKeyDataAesId;
121 ctx->keySize = 32;
122 ctx->cbcMode = 1;
123 } else if(transform->id == xmlSecMSCngTransformAes128GcmId) {
124 ctx->pszAlgId = BCRYPT_AES_ALGORITHM;
125 ctx->keyId = xmlSecMSCngKeyDataAesId;
126 ctx->keySize = 16;
127 ctx->cbcMode = 0;
128 } else if(transform->id == xmlSecMSCngTransformAes192GcmId) {
129 ctx->pszAlgId = BCRYPT_AES_ALGORITHM;
130 ctx->keyId = xmlSecMSCngKeyDataAesId;
131 ctx->keySize = 24;
132 ctx->cbcMode = 0;
133 } else if(transform->id == xmlSecMSCngTransformAes256GcmId) {
134 ctx->pszAlgId = BCRYPT_AES_ALGORITHM;
135 ctx->keyId = xmlSecMSCngKeyDataAesId;
136 ctx->keySize = 32;
137 ctx->cbcMode = 0;
138 } else
139 #endif /* XMLSEC_NO_AES */
140
141 #ifndef XMLSEC_NO_DES
142 if(transform->id == xmlSecMSCngTransformDes3CbcId) {
143 ctx->pszAlgId = BCRYPT_3DES_ALGORITHM;
144 ctx->keyId = xmlSecMSCngKeyDataDesId;
145 ctx->keySize = 24;
146 ctx->cbcMode = 1;
147 } else
148 #endif /* XMLSEC_NO_DES */
149
150 {
151 xmlSecInvalidTransfromError(transform)
152 return(-1);
153 }
154
155 status = BCryptOpenAlgorithmProvider(
156 &ctx->hAlg,
157 ctx->pszAlgId,
158 NULL,
159 0);
160 if(status != STATUS_SUCCESS) {
161 xmlSecMSCngNtError("BCryptOpenAlgorithmProvider",
162 xmlSecTransformGetName(transform), status);
163 return(-1);
164 }
165
166 if(ctx->cbcMode) {
167 status = BCryptSetProperty(ctx->hAlg,
168 BCRYPT_CHAINING_MODE,
169 (PUCHAR)BCRYPT_CHAIN_MODE_CBC,
170 sizeof(BCRYPT_CHAIN_MODE_CBC),
171 0);
172 } else {
173 status = BCryptSetProperty(ctx->hAlg,
174 BCRYPT_CHAINING_MODE,
175 (PUCHAR)BCRYPT_CHAIN_MODE_GCM,
176 sizeof(BCRYPT_CHAIN_MODE_GCM),
177 0);
178 }
179 if(status != STATUS_SUCCESS) {
180 xmlSecMSCngNtError("BCryptSetProperty", xmlSecTransformGetName(transform), status);
181 return(-1);
182 }
183
184 ctx->ctxInitialized = 0;
185
186 return(0);
187 }
188
189 static void
xmlSecMSCngBlockCipherFinalize(xmlSecTransformPtr transform)190 xmlSecMSCngBlockCipherFinalize(xmlSecTransformPtr transform) {
191 xmlSecMSCngBlockCipherCtxPtr ctx;
192
193 xmlSecAssert(xmlSecMSCngBlockCipherCheckId(transform));
194 xmlSecAssert(xmlSecTransformCheckSize(transform, xmlSecMSCngBlockCipherSize));
195
196 ctx = xmlSecMSCngBlockCipherGetCtx(transform);
197 xmlSecAssert(ctx != NULL);
198
199 if(ctx->pbIV != NULL) {
200 xmlFree(ctx->pbIV);
201 }
202
203 if(ctx->authInfo.pbNonce != NULL) {
204 xmlFree(ctx->authInfo.pbNonce);
205 }
206 if(ctx->authInfo.pbTag != NULL) {
207 xmlFree(ctx->authInfo.pbTag);
208 }
209 if(ctx->authInfo.pbMacContext != NULL) {
210 xmlFree(ctx->authInfo.pbMacContext);
211 }
212
213 if(ctx->hKey != NULL) {
214 BCryptDestroyKey(ctx->hKey);
215 }
216
217 if(ctx->pbKeyObject != NULL) {
218 xmlFree(ctx->pbKeyObject);
219 }
220
221 if(ctx->hAlg != NULL) {
222 BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
223 }
224
225 memset(ctx, 0, sizeof(xmlSecMSCngBlockCipherCtx));
226 }
227
228 static int
xmlSecMSCngBlockCipherSetKeyReq(xmlSecTransformPtr transform,xmlSecKeyReqPtr keyReq)229 xmlSecMSCngBlockCipherSetKeyReq(xmlSecTransformPtr transform, xmlSecKeyReqPtr keyReq) {
230 xmlSecMSCngBlockCipherCtxPtr ctx;
231
232 xmlSecAssert2(xmlSecMSCngBlockCipherCheckId(transform), -1);
233 xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
234 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCngBlockCipherSize), -1);
235 xmlSecAssert2(keyReq != NULL, -1);
236
237 ctx = xmlSecMSCngBlockCipherGetCtx(transform);
238 xmlSecAssert2(ctx != NULL, -1);
239 xmlSecAssert2(ctx->hAlg != 0, -1);
240
241 keyReq->keyId = ctx->keyId;
242 keyReq->keyType = xmlSecKeyDataTypeSymmetric;
243 if(transform->operation == xmlSecTransformOperationEncrypt) {
244 keyReq->keyUsage = xmlSecKeyUsageEncrypt;
245 } else {
246 keyReq->keyUsage = xmlSecKeyUsageDecrypt;
247 }
248
249 keyReq->keyBitsSize = 8 * ctx->keySize;
250 return(0);
251 }
252
253 static int
xmlSecMSCngBlockCipherSetKey(xmlSecTransformPtr transform,xmlSecKeyPtr key)254 xmlSecMSCngBlockCipherSetKey(xmlSecTransformPtr transform, xmlSecKeyPtr key) {
255 xmlSecMSCngBlockCipherCtxPtr ctx;
256 xmlSecBufferPtr buffer;
257 xmlSecBuffer blob;
258 BCRYPT_KEY_DATA_BLOB_HEADER* blobHeader;
259 xmlSecSize blobHeaderLen;
260 BYTE* bufData;
261 DWORD dwKeyObjectLength, bytesWritten;
262 NTSTATUS status;
263 int ret;
264
265 xmlSecAssert2(xmlSecMSCngBlockCipherCheckId(transform), -1);
266 xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
267 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCngBlockCipherSize), -1);
268 xmlSecAssert2(key != NULL, -1);
269
270 /* get the symmetric key into bufData */
271 ctx = xmlSecMSCngBlockCipherGetCtx(transform);
272 xmlSecAssert2(ctx != NULL, -1);
273 xmlSecAssert2(ctx->hKey == 0, -1);
274 xmlSecAssert2(ctx->keyId != NULL, -1);
275 xmlSecAssert2(xmlSecKeyCheckId(key, ctx->keyId), -1);
276 xmlSecAssert2(ctx->keySize > 0, -1);
277 xmlSecAssert2(ctx->pbKeyObject == NULL, -1);
278
279 buffer = xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyGetValue(key));
280 xmlSecAssert2(buffer != NULL, -1);
281
282 if(xmlSecBufferGetSize(buffer) < ctx->keySize) {
283 xmlSecInvalidKeyDataSizeError(xmlSecBufferGetSize(buffer), ctx->keySize,
284 xmlSecTransformGetName(transform));
285 return(-1);
286 }
287
288 bufData = xmlSecBufferGetData(buffer);
289 xmlSecAssert2(bufData != NULL, -1);
290
291 /* allocate the key object */
292 dwKeyObjectLength = 0;
293 status = BCryptGetProperty(ctx->hAlg,
294 BCRYPT_OBJECT_LENGTH,
295 (PUCHAR)&dwKeyObjectLength,
296 (ULONG)sizeof(DWORD),
297 &bytesWritten, 0);
298 if(status != STATUS_SUCCESS) {
299 xmlSecMSCngNtError("BCryptGetProperty",
300 xmlSecTransformGetName(transform), status);
301 return(-1);
302 }
303
304 ctx->pbKeyObject = xmlMalloc(dwKeyObjectLength);
305 if(ctx->pbKeyObject == NULL) {
306 xmlSecMallocError(dwKeyObjectLength, xmlSecTransformGetName(transform));
307 return(-1);
308 }
309
310 /* prefix the key with a BCRYPT_KEY_DATA_BLOB_HEADER */
311 blobHeaderLen = sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + xmlSecBufferGetSize(buffer);
312 ret = xmlSecBufferInitialize(&blob, blobHeaderLen);
313 if(ret < 0) {
314 xmlSecInternalError2("xmlSecBufferInitialize",
315 xmlSecTransformGetName(transform), "size=%d", blobHeaderLen);
316 return(-1);
317 }
318
319 blobHeader = (BCRYPT_KEY_DATA_BLOB_HEADER*)xmlSecBufferGetData(&blob);
320 blobHeader->dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC;
321 blobHeader->dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1;
322 blobHeader->cbKeyData = (ULONG)xmlSecBufferGetSize(buffer);
323 memcpy(xmlSecBufferGetData(&blob) + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER),
324 bufData, xmlSecBufferGetSize(buffer));
325 xmlSecBufferSetSize(&blob, blobHeaderLen);
326
327 /* perform the actual import */
328 status = BCryptImportKey(ctx->hAlg,
329 NULL,
330 BCRYPT_KEY_DATA_BLOB,
331 &ctx->hKey,
332 ctx->pbKeyObject,
333 dwKeyObjectLength,
334 xmlSecBufferGetData(&blob),
335 (ULONG)xmlSecBufferGetSize(&blob),
336 0);
337 if(status != STATUS_SUCCESS) {
338 xmlSecMSCngNtError("BCryptImportKey",
339 xmlSecTransformGetName(transform), status);
340 xmlSecBufferFinalize(&blob);
341 return(-1);
342 }
343
344 xmlSecBufferFinalize(&blob);
345
346 return(0);
347 }
348
xmlSecMSCngCBCBlockCipherCtxInit(xmlSecMSCngBlockCipherCtxPtr ctx,xmlSecBufferPtr in,xmlSecBufferPtr out,int encrypt,const xmlChar * cipherName,xmlSecTransformCtxPtr transformCtx)349 static int xmlSecMSCngCBCBlockCipherCtxInit(xmlSecMSCngBlockCipherCtxPtr ctx,
350 xmlSecBufferPtr in, xmlSecBufferPtr out, int encrypt,
351 const xmlChar* cipherName, xmlSecTransformCtxPtr transformCtx) {
352
353 NTSTATUS status;
354 int ret;
355
356 /* unreferenced parameter */
357 (void)transformCtx;
358
359 xmlSecAssert2(ctx != NULL, -1);
360 xmlSecAssert2(ctx->hKey != 0, -1);
361 xmlSecAssert2(ctx->ctxInitialized == 0, -1);
362 xmlSecAssert2(ctx->dwBlockLen > 0, -1);
363 xmlSecAssert2(in != NULL, -1);
364 xmlSecAssert2(out != NULL, -1);
365 xmlSecAssert2(transformCtx != NULL, -1);
366
367 /* iv len == block len */
368 ctx->cbIV = ctx->dwBlockLen;
369
370 if(encrypt) {
371 unsigned char* iv;
372 xmlSecSize outSize;
373
374 /* allocate space for IV */
375 outSize = xmlSecBufferGetSize(out);
376 ret = xmlSecBufferSetSize(out, outSize + ctx->dwBlockLen);
377 if(ret < 0) {
378 xmlSecInternalError2("xmlSecBufferSetSize", cipherName,
379 "size=%d", outSize + ctx->dwBlockLen);
380 return(-1);
381 }
382 iv = xmlSecBufferGetData(out) + outSize;
383
384 /* generate and use random iv */
385 status = BCryptGenRandom(NULL,
386 (PBYTE)iv,
387 ctx->dwBlockLen,
388 BCRYPT_USE_SYSTEM_PREFERRED_RNG);
389 if(status != STATUS_SUCCESS) {
390 xmlSecMSCngNtError("BCryptGenRandom", cipherName, status);
391 return(-1);
392 }
393
394 if(ctx->pbIV == NULL) {
395 ctx->pbIV = xmlMalloc(ctx->dwBlockLen);
396 }
397 if(ctx->pbIV == NULL) {
398 xmlSecMallocError(ctx->dwBlockLen, cipherName);
399 return(-1);
400 }
401
402 memcpy(ctx->pbIV, iv, ctx->dwBlockLen);
403 } else {
404 /* if we don't have enough data, exit and hope that
405 * we'll have iv next time */
406 if(xmlSecBufferGetSize(in) < XMLSEC_SIZE_BAD_CAST(ctx->dwBlockLen)) {
407 return(0);
408 }
409 xmlSecAssert2(xmlSecBufferGetData(in) != NULL, -1);
410
411 /* set iv */
412 ctx->pbIV = xmlMalloc(ctx->dwBlockLen);
413 if(ctx->pbIV == NULL) {
414 xmlSecMallocError(ctx->dwBlockLen, cipherName);
415 return(-1);
416 }
417 memcpy(ctx->pbIV, xmlSecBufferGetData(in), ctx->dwBlockLen);
418
419 /* and remove from input */
420 ret = xmlSecBufferRemoveHead(in, ctx->dwBlockLen);
421 if(ret < 0) {
422 xmlSecInternalError2("xmlSecBufferRemoveHead", cipherName,
423 "size=%d", ctx->dwBlockLen);
424 return(-1);
425
426 }
427 }
428
429 ctx->ctxInitialized = 1;
430 return(0);
431 }
432
xmlSecMSCngGCMBlockCipherCtxInit(xmlSecMSCngBlockCipherCtxPtr ctx,xmlSecBufferPtr in,xmlSecBufferPtr out,int encrypt,int last,const xmlChar * cipherName,xmlSecTransformCtxPtr transformCtx)433 static int xmlSecMSCngGCMBlockCipherCtxInit(xmlSecMSCngBlockCipherCtxPtr ctx,
434 xmlSecBufferPtr in, xmlSecBufferPtr out, int encrypt, int last,
435 const xmlChar* cipherName, xmlSecTransformCtxPtr transformCtx) {
436
437 NTSTATUS status;
438 int ret;
439 xmlSecByte *bufferPtr;
440 xmlSecSize bufferSize;
441 DWORD bytesRead;
442 BCRYPT_AUTH_TAG_LENGTHS_STRUCT authTagLengths;
443
444 /* unreferenced parameter */
445 (void)transformCtx;
446
447 xmlSecAssert2(ctx != NULL, -1);
448 xmlSecAssert2(ctx->hKey != 0, -1);
449 xmlSecAssert2(ctx->ctxInitialized == 0, -1);
450 xmlSecAssert2(ctx->dwBlockLen > 0, -1);
451 xmlSecAssert2(in != NULL, -1);
452 xmlSecAssert2(out != NULL, -1);
453 xmlSecAssert2(transformCtx != NULL, -1);
454
455 /* Check that we haven't already allocated space for the nonce. Might
456 * happen if the context is initialised more that once */
457 if(ctx->authInfo.pbNonce == NULL) {
458 ctx->authInfo.pbNonce = xmlMalloc(xmlSecMSCngAesGcmNonceLengthInBytes);
459 if(ctx->authInfo.pbNonce == NULL) {
460 xmlSecMallocError(xmlSecMSCngAesGcmNonceLengthInBytes, cipherName);
461 return(-1);
462 }
463 }
464 ctx->authInfo.cbNonce = xmlSecMSCngAesGcmNonceLengthInBytes;
465
466 /* Tag length is 128 bits */
467 /* See http://www.w3.org/TR/xmlenc-core1/#sec-AES-GCM */
468 if(ctx->authInfo.pbTag == NULL) {
469 ctx->authInfo.pbTag = xmlMalloc(xmlSecMSCngAesGcmTagLengthInBytes);
470 if(ctx->authInfo.pbTag == NULL) {
471 xmlSecMallocError(xmlSecMSCngAesGcmTagLengthInBytes, cipherName);
472 return(-1);
473 }
474 }
475 memset(ctx->authInfo.pbTag, 0, xmlSecMSCngAesGcmTagLengthInBytes);
476 ctx->authInfo.cbTag = xmlSecMSCngAesGcmTagLengthInBytes;
477
478 if(last == 0) {
479 /* Need some working buffers */
480
481 /* iv len == block len */
482 if(ctx->pbIV == NULL) {
483 ctx->pbIV = xmlMalloc(ctx->dwBlockLen);
484 if(ctx->pbIV == NULL) {
485 xmlSecMallocError(ctx->dwBlockLen, cipherName);
486 return(-1);
487 }
488 }
489 ctx->cbIV = ctx->dwBlockLen;
490 memset(ctx->pbIV, 0, ctx->dwBlockLen);
491
492 /* Setup an empty MAC context if we're chaining calls */
493 status = BCryptGetProperty(ctx->hAlg,
494 BCRYPT_AUTH_TAG_LENGTH,
495 (PUCHAR)&authTagLengths,
496 (ULONG)sizeof(authTagLengths),
497 &bytesRead,
498 0);
499 if(status != STATUS_SUCCESS) {
500 xmlSecMSCngNtError("BCryptGetProperty", cipherName, status);
501 return(-1);
502 }
503
504 if(ctx->authInfo.pbMacContext == NULL) {
505 ctx->authInfo.pbMacContext = xmlMalloc(authTagLengths.dwMaxLength);
506 if(ctx->authInfo.pbMacContext == NULL) {
507 xmlSecMallocError(authTagLengths.dwMaxLength, cipherName);
508 return(-1);
509 }
510 }
511 ctx->authInfo.cbMacContext = authTagLengths.dwMaxLength;
512 memset(ctx->authInfo.pbMacContext, 0, authTagLengths.dwMaxLength);
513 ctx->authInfo.dwFlags |= BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG;
514 } else {
515 ctx->pbIV = NULL;
516 ctx->cbIV = 0;
517 }
518
519 if(encrypt) {
520
521 /* allocate space for nonce in the output buffer - it is 96 bits for GCM mode */
522 /* See http://www.w3.org/TR/xmlenc-core1/#sec-AES-GCM */
523 bufferSize = xmlSecBufferGetSize(out);
524 ret = xmlSecBufferSetSize(out, bufferSize + xmlSecMSCngAesGcmNonceLengthInBytes);
525 if(ret < 0) {
526 xmlSecInternalError2("xmlSecBufferSetSize", cipherName,
527 "size=%d", bufferSize + xmlSecMSCngAesGcmNonceLengthInBytes);
528 return(-1);
529 }
530 bufferPtr = xmlSecBufferGetData(out) + bufferSize;
531
532 /* generate and use random nonce */
533 status = BCryptGenRandom(NULL,
534 (PBYTE)bufferPtr,
535 xmlSecMSCngAesGcmNonceLengthInBytes,
536 BCRYPT_USE_SYSTEM_PREFERRED_RNG);
537 if(status != STATUS_SUCCESS) {
538 xmlSecMSCngNtError("BCryptGenRandom", cipherName, status);
539 return(-1);
540 }
541 /* copy the nonce into the padding info */
542 memcpy(ctx->authInfo.pbNonce, bufferPtr, xmlSecMSCngAesGcmNonceLengthInBytes);
543
544 } else {
545 /* if we don't have enough data, exit and hope that
546 we'll have the nonce next time */
547 bufferSize = xmlSecBufferGetSize(in);
548 if(bufferSize < xmlSecMSCngAesGcmNonceLengthInBytes) {
549 return(0);
550 }
551
552 bufferPtr = xmlSecBufferGetData(in);
553
554 xmlSecAssert2(bufferPtr != NULL, -1);
555
556 /* set nonce */
557 memcpy(ctx->authInfo.pbNonce, bufferPtr, xmlSecMSCngAesGcmNonceLengthInBytes);
558
559 /* remove nonce from input */
560 ret = xmlSecBufferRemoveHead(in, xmlSecMSCngAesGcmNonceLengthInBytes);
561 if(ret < 0) {
562 xmlSecInternalError2("xmlSecBufferRemoveHead", cipherName,
563 "size=%d", xmlSecMSCngAesGcmNonceLengthInBytes);
564 return(-1);
565 }
566 }
567
568 ctx->ctxInitialized = 1;
569 return(0);
570 }
571
572 static int
xmlSecMSCngBlockCipherCtxInit(xmlSecMSCngBlockCipherCtxPtr ctx,xmlSecBufferPtr in,xmlSecBufferPtr out,int encrypt,int last,const xmlChar * cipherName,xmlSecTransformCtxPtr transformCtx)573 xmlSecMSCngBlockCipherCtxInit(xmlSecMSCngBlockCipherCtxPtr ctx,
574 xmlSecBufferPtr in, xmlSecBufferPtr out, int encrypt, int last,
575 const xmlChar* cipherName, xmlSecTransformCtxPtr transformCtx) {
576 NTSTATUS status;
577 DWORD dwBlockLenLen;
578
579 xmlSecAssert2(ctx != NULL, -1);
580 xmlSecAssert2(ctx->hKey != 0, -1);
581 xmlSecAssert2(ctx->hAlg != 0, -1);
582 xmlSecAssert2(ctx->ctxInitialized == 0, -1);
583
584 /* Get the cipher block length */
585 dwBlockLenLen = sizeof(DWORD);
586 status = BCryptGetProperty(ctx->hAlg,
587 BCRYPT_BLOCK_LENGTH,
588 (PUCHAR)&ctx->dwBlockLen,
589 sizeof(ctx->dwBlockLen),
590 &dwBlockLenLen,
591 0);
592 if(status != STATUS_SUCCESS) {
593 xmlSecMSCngNtError("BCryptGetProperty", cipherName, status);
594 return(-1);
595 }
596
597 xmlSecAssert2(ctx->dwBlockLen > 0, -1);
598
599 if(ctx->cbcMode) {
600 return xmlSecMSCngCBCBlockCipherCtxInit(ctx, in, out, encrypt,
601 cipherName, transformCtx);
602 } else {
603 return xmlSecMSCngGCMBlockCipherCtxInit(ctx, in, out, encrypt, last,
604 cipherName, transformCtx);
605 }
606 }
607
608 static int
xmlSecMSCngCBCBlockCipherCtxUpdate(xmlSecMSCngBlockCipherCtxPtr ctx,xmlSecBufferPtr in,xmlSecBufferPtr out,int encrypt,const xmlChar * cipherName,xmlSecTransformCtxPtr transformCtx)609 xmlSecMSCngCBCBlockCipherCtxUpdate(xmlSecMSCngBlockCipherCtxPtr ctx,
610 xmlSecBufferPtr in, xmlSecBufferPtr out, int encrypt,
611 const xmlChar* cipherName, xmlSecTransformCtxPtr transformCtx) {
612 xmlSecSize inSize, inBlocks, outSize;
613 unsigned char* outBuf;
614 unsigned char* inBuf;
615 DWORD dwCLen;
616 NTSTATUS status;
617 int ret;
618
619 /* unreferenced parameter */
620 (void)transformCtx;
621
622 xmlSecAssert2(ctx != NULL, -1);
623 xmlSecAssert2(ctx->ctxInitialized != 0, -1);
624 xmlSecAssert2(ctx->dwBlockLen > 0, -1);
625 xmlSecAssert2(in != NULL, -1);
626 xmlSecAssert2(out != NULL, -1);
627 xmlSecAssert2(transformCtx != NULL, -1);
628
629 inSize = xmlSecBufferGetSize(in);
630 outSize = xmlSecBufferGetSize(out);
631
632 if(inSize < XMLSEC_SIZE_BAD_CAST(ctx->dwBlockLen)) {
633 return(0);
634 }
635
636 if(encrypt) {
637 inBlocks = inSize / XMLSEC_SIZE_BAD_CAST(ctx->dwBlockLen);
638 } else {
639 /* we want to have the last block in the input buffer
640 * for padding check */
641 inBlocks = (inSize - 1) / XMLSEC_SIZE_BAD_CAST(ctx->dwBlockLen);
642 }
643 inSize = inBlocks * XMLSEC_SIZE_BAD_CAST(ctx->dwBlockLen);
644
645 /* we write out the input size plus maybe one block */
646 ret = xmlSecBufferSetMaxSize(out, outSize + inSize + ctx->dwBlockLen);
647 if(ret < 0) {
648 xmlSecInternalError2("xmlSecBufferSetMaxSize", cipherName,
649 "size=%d", outSize + inSize + ctx->dwBlockLen);
650 return(-1);
651 }
652 outBuf = xmlSecBufferGetData(out) + outSize;
653 inBuf = xmlSecBufferGetData(in);
654 xmlSecAssert2(inBuf != NULL, -1);
655
656 dwCLen = (DWORD)inSize;
657 if(encrypt) {
658 status = BCryptEncrypt(ctx->hKey,
659 inBuf,
660 (ULONG)inSize,
661 NULL,
662 ctx->pbIV,
663 ctx->cbIV,
664 outBuf,
665 (ULONG)inSize,
666 &dwCLen,
667 0);
668 if(status != STATUS_SUCCESS) {
669 xmlSecMSCngNtError("BCryptEncrypt", cipherName, status);
670 return(-1);
671 }
672
673 /* check if we really have encrypted the numbers of bytes that we
674 * requested */
675 if(dwCLen != inSize) {
676 xmlSecInternalError2("BCryptEncrypt", cipherName, "size=%ld",
677 dwCLen);
678 return(-1);
679 }
680 } else {
681 status = BCryptDecrypt(ctx->hKey,
682 inBuf,
683 (ULONG)inSize,
684 NULL,
685 ctx->pbIV,
686 ctx->cbIV,
687 outBuf,
688 (ULONG)inSize,
689 &dwCLen,
690 0);
691 if(status != STATUS_SUCCESS) {
692 xmlSecMSCngNtError("BCryptDecrypt", cipherName, status);
693 return(-1);
694 }
695
696 /* check if we really have decrypted the numbers of bytes that we
697 * requested */
698 if(dwCLen != inSize) {
699 xmlSecInternalError2("BCryptDecrypt", cipherName, "size=%ld",
700 dwCLen);
701 return(-1);
702 }
703 }
704
705 /* set correct output buffer size */
706 ret = xmlSecBufferSetSize(out, outSize + inSize);
707 if(ret < 0) {
708 xmlSecInternalError2("xmlSecBufferSetSize", cipherName, "size=%d",
709 outSize + inSize);
710 return(-1);
711 }
712
713 /* remove the processed block from input */
714 ret = xmlSecBufferRemoveHead(in, inSize);
715 if(ret < 0) {
716 xmlSecInternalError2("xmlSecBufferRemoveHead", cipherName, "size=%d",
717 inSize);
718 return(-1);
719 }
720
721 return(0);
722 }
723
724 static int
xmlSecMSCngGCMBlockCipherCtxUpdate(xmlSecMSCngBlockCipherCtxPtr ctx,xmlSecBufferPtr in,xmlSecBufferPtr out,int encrypt,int last,const xmlChar * cipherName,xmlSecTransformCtxPtr transformCtx)725 xmlSecMSCngGCMBlockCipherCtxUpdate(xmlSecMSCngBlockCipherCtxPtr ctx,
726 xmlSecBufferPtr in, xmlSecBufferPtr out, int encrypt, int last,
727 const xmlChar* cipherName, xmlSecTransformCtxPtr transformCtx) {
728
729 NTSTATUS status;
730 xmlSecSize inSize, outSize;
731 xmlSecByte *inBuf, *outBuf;
732 DWORD dwCLen;
733 int ret;
734
735 /* unreferenced parameter */
736 (void)transformCtx;
737
738 xmlSecAssert2(ctx != NULL, -1);
739 xmlSecAssert2(ctx->ctxInitialized != 0, -1);
740 xmlSecAssert2(ctx->dwBlockLen > 0, -1);
741 xmlSecAssert2(in != NULL, -1);
742 xmlSecAssert2(out != NULL, -1);
743 xmlSecAssert2(transformCtx != NULL, -1);
744
745 if(last != 0) {
746 /* We handle everything in finalize for the last block of data */
747 return(0);
748 }
749
750 inBuf = xmlSecBufferGetData(in);
751 xmlSecAssert2(inBuf != NULL, -1);
752
753 if(xmlSecBufferGetSize(in) < ctx->dwBlockLen) {
754 return 0;
755 }
756
757 if(encrypt) {
758 /* Round to the block size. We will finalize this later */
759 inSize = (xmlSecBufferGetSize(in) / XMLSEC_SIZE_BAD_CAST(ctx->dwBlockLen)) * XMLSEC_SIZE_BAD_CAST(ctx->dwBlockLen);
760 } else {
761 /* If we've been called here, we know there is more data
762 * to come, but we don't know how much. The spec tells us that
763 * the tag is the last 16 bytes of the data when decrypting, so to make sure
764 * we don't try to decrypt it, we leave at least 16 bytes in the buffer
765 * until we know we're processing the last one */
766 inSize = ((xmlSecBufferGetSize(in) - xmlSecMSCngAesGcmTagLengthInBytes) / XMLSEC_SIZE_BAD_CAST(ctx->dwBlockLen)) * XMLSEC_SIZE_BAD_CAST(ctx->dwBlockLen);
767 if (inSize < ctx->dwBlockLen) {
768 return 0;
769 }
770 }
771
772 outSize = xmlSecBufferGetSize(out);
773 ret = xmlSecBufferSetMaxSize(out, outSize + inSize);
774 if(ret < 0) {
775 xmlSecInternalError2("xmlSecBufferSetMaxSize", cipherName,
776 "size=%d", outSize + inSize);
777 return(-1);
778 }
779
780 outBuf = xmlSecBufferGetData(out) + outSize;
781
782 dwCLen = 0;
783 if(encrypt) {
784 status = BCryptEncrypt(ctx->hKey,
785 inBuf,
786 (ULONG)inSize,
787 &ctx->authInfo,
788 ctx->pbIV,
789 ctx->cbIV,
790 outBuf,
791 (ULONG)inSize,
792 &dwCLen,
793 0);
794
795 if(status != STATUS_SUCCESS) {
796 xmlSecMSCngNtError("BCryptEncrypt", cipherName, status);
797 return(-1);
798 }
799
800 /* check if we really have encrypted the numbers of bytes that we
801 * requested */
802 if(dwCLen != inSize) {
803 xmlSecInternalError2("BCryptEncrypt", cipherName, "size=%ld",
804 dwCLen);
805 return(-1);
806 }
807
808 } else {
809 status = BCryptDecrypt(ctx->hKey,
810 inBuf,
811 (ULONG)inSize,
812 &ctx->authInfo,
813 ctx->pbIV,
814 ctx->cbIV,
815 outBuf,
816 (ULONG)inSize,
817 &dwCLen,
818 0);
819
820 if(status != STATUS_SUCCESS) {
821 xmlSecMSCngNtError("BCryptDecrypt", cipherName, status);
822 return(-1);
823 }
824
825 /* check if we really have decrypted the numbers of bytes that we
826 * requested */
827 if(dwCLen != inSize) {
828 xmlSecInternalError2("BCryptDecrypt", cipherName, "size=%ld",
829 dwCLen);
830 return(-1);
831 }
832 }
833
834 /* set correct output buffer size */
835 ret = xmlSecBufferSetSize(out, outSize + dwCLen);
836 if(ret < 0) {
837 xmlSecInternalError2("xmlSecBufferSetSize", cipherName, "size=%d",
838 outSize + dwCLen);
839 return(-1);
840 }
841
842 /* remove the processed data from input */
843 ret = xmlSecBufferRemoveHead(in, dwCLen);
844 if(ret < 0) {
845 xmlSecInternalError2("xmlSecBufferRemoveHead", cipherName, "size=%d",
846 dwCLen);
847 return(-1);
848 }
849
850 return(0);
851 }
852
853 static int
xmlSecMSCngBlockCipherCtxUpdate(xmlSecMSCngBlockCipherCtxPtr ctx,xmlSecBufferPtr in,xmlSecBufferPtr out,int encrypt,int last,const xmlChar * cipherName,xmlSecTransformCtxPtr transformCtx)854 xmlSecMSCngBlockCipherCtxUpdate(xmlSecMSCngBlockCipherCtxPtr ctx,
855 xmlSecBufferPtr in, xmlSecBufferPtr out, int encrypt, int last,
856 const xmlChar* cipherName, xmlSecTransformCtxPtr transformCtx) {
857
858 xmlSecAssert2(ctx != NULL, -1);
859
860 if(ctx->cbcMode) {
861 return xmlSecMSCngCBCBlockCipherCtxUpdate(ctx, in, out, encrypt,
862 cipherName, transformCtx);
863 } else {
864 return xmlSecMSCngGCMBlockCipherCtxUpdate(ctx, in, out, encrypt, last,
865 cipherName, transformCtx);
866 }
867 }
868
869 static int
xmlSecMSCngCBCBlockCipherCtxFinal(xmlSecMSCngBlockCipherCtxPtr ctx,xmlSecBufferPtr in,xmlSecBufferPtr out,int encrypt,const xmlChar * cipherName,xmlSecTransformCtxPtr transformCtx)870 xmlSecMSCngCBCBlockCipherCtxFinal(xmlSecMSCngBlockCipherCtxPtr ctx,
871 xmlSecBufferPtr in, xmlSecBufferPtr out, int encrypt,
872 const xmlChar* cipherName, xmlSecTransformCtxPtr transformCtx) {
873 xmlSecSize inSize, outSize;
874 int outLen;
875 unsigned char* inBuf;
876 unsigned char* outBuf;
877 DWORD dwCLen;
878 NTSTATUS status;
879 int ret;
880
881 /* unreferenced parameter */
882 (void)transformCtx;
883
884 inSize = xmlSecBufferGetSize(in);
885 outSize = xmlSecBufferGetSize(out);
886
887 if(encrypt != 0) {
888 xmlSecAssert2(inSize < XMLSEC_SIZE_BAD_CAST(ctx->dwBlockLen), -1);
889
890 /* create padding */
891 ret = xmlSecBufferSetMaxSize(in, ctx->dwBlockLen);
892 if(ret < 0) {
893 xmlSecInternalError2("xmlSecBufferSetMaxSize", cipherName,
894 "size=%d", ctx->dwBlockLen);
895 return(-1);
896 }
897 inBuf = xmlSecBufferGetData(in);
898
899 /* create random padding */
900 if(XMLSEC_SIZE_BAD_CAST(ctx->dwBlockLen) > (inSize + 1)) {
901 status = BCryptGenRandom(NULL,
902 (PBYTE) inBuf + inSize,
903 (ULONG)(ctx->dwBlockLen - inSize - 1),
904 BCRYPT_USE_SYSTEM_PREFERRED_RNG);
905 if(status != STATUS_SUCCESS) {
906 xmlSecMSCngNtError("BCryptGetProperty", cipherName, status);
907 return(-1);
908 }
909 }
910 inBuf[ctx->dwBlockLen - 1] = (unsigned char)(ctx->dwBlockLen - inSize);
911 inSize = ctx->dwBlockLen;
912 } else {
913 if(inSize != XMLSEC_SIZE_BAD_CAST(ctx->dwBlockLen)) {
914 xmlSecInvalidSizeError("Input data", inSize, ctx->dwBlockLen, cipherName);
915 return(-1);
916 }
917 inBuf = xmlSecBufferGetData(in);
918 }
919
920 /* process last block */
921 ret = xmlSecBufferSetMaxSize(out, outSize + 2 * ctx->dwBlockLen);
922 if(ret < 0) {
923 xmlSecInternalError2("xmlSecBufferSetMaxSize", cipherName, "size=%d",
924 outSize + 2 * ctx->dwBlockLen);
925 return(-1);
926 }
927
928 outBuf = xmlSecBufferGetData(out) + outSize;
929
930 dwCLen = (ULONG)inSize;
931 if(encrypt) {
932 status = BCryptEncrypt(ctx->hKey,
933 inBuf,
934 (ULONG)inSize,
935 NULL,
936 ctx->pbIV,
937 ctx->cbIV,
938 outBuf,
939 (ULONG)(inSize + ctx->dwBlockLen),
940 &dwCLen,
941 0);
942 if(status != STATUS_SUCCESS) {
943 xmlSecMSCngNtError("BCryptDecrypt", cipherName, status);
944 return(-1);
945 }
946
947 /* check if we really have encrypted the numbers of bytes that we
948 * requested */
949 if(dwCLen != inSize) {
950 xmlSecInternalError2("BCryptEncrypt", cipherName, "size=%ld",
951 dwCLen);
952 return(-1);
953 }
954 } else {
955 status = BCryptDecrypt(ctx->hKey,
956 inBuf,
957 (ULONG)inSize,
958 NULL,
959 ctx->pbIV,
960 ctx->cbIV,
961 outBuf,
962 (ULONG)inSize,
963 &dwCLen,
964 0);
965 if(status != STATUS_SUCCESS) {
966 xmlSecMSCngNtError("BCryptDecrypt", cipherName, status);
967 return(-1);
968 }
969
970 /* check if we really have decrypted the numbers of bytes that we
971 * requested */
972 if(dwCLen != inSize) {
973 xmlSecInternalError2("BCryptDecrypt", cipherName, "size=%ld",
974 dwCLen);
975 return(-1);
976 }
977 }
978
979 if(encrypt == 0) {
980 /* check padding */
981 if(inSize < outBuf[ctx->dwBlockLen - 1]) {
982 xmlSecInvalidSizeLessThanError("Input data padding", inSize,
983 outBuf[ctx->dwBlockLen - 1], cipherName);
984 return(-1);
985 }
986 outLen = (int)(inSize - outBuf[ctx->dwBlockLen - 1]);
987 } else {
988 outLen = (int)inSize;
989 }
990
991 /* set correct output buffer size */
992 ret = xmlSecBufferSetSize(out, outSize + outLen);
993 if(ret < 0) {
994 xmlSecInternalError2("xmlSecBufferSetSize", cipherName, "size=%d",
995 outSize + outLen);
996 return(-1);
997 }
998
999 /* remove the processed block from input */
1000 ret = xmlSecBufferRemoveHead(in, inSize);
1001 if(ret < 0) {
1002 xmlSecInternalError2("xmlSecBufferRemoveHead", cipherName, "size=%d",
1003 inSize);
1004 return(-1);
1005 }
1006
1007 return(0);
1008 }
1009
1010 static int
xmlSecMSCngGCMBlockCipherCtxFinal(xmlSecMSCngBlockCipherCtxPtr ctx,xmlSecBufferPtr in,xmlSecBufferPtr out,int encrypt,const xmlChar * cipherName,xmlSecTransformCtxPtr transformCtx)1011 xmlSecMSCngGCMBlockCipherCtxFinal(xmlSecMSCngBlockCipherCtxPtr ctx,
1012 xmlSecBufferPtr in, xmlSecBufferPtr out, int encrypt,
1013 const xmlChar* cipherName, xmlSecTransformCtxPtr transformCtx)
1014 {
1015 xmlSecByte *inBuf, *outBuf;
1016 xmlSecSize inBufSize, outBufSize, outLen;
1017 DWORD dwCLen;
1018 int ret;
1019 NTSTATUS status;
1020
1021 /* unreferenced parameter */
1022 (void)transformCtx;
1023
1024 ctx->authInfo.dwFlags &= ~BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG; /* clear chaining flag */
1025
1026 outBufSize = xmlSecBufferGetSize(out);
1027 inBufSize = xmlSecBufferGetSize(in);
1028 inBuf = xmlSecBufferGetData(in);
1029
1030 if(encrypt) {
1031 ret = xmlSecBufferSetMaxSize(out,
1032 outBufSize + inBufSize + xmlSecMSCngAesGcmTagLengthInBytes); /* add space for the tag */
1033 if(ret < 0) {
1034 xmlSecInternalError2("xmlSecBufferSetMaxSize", cipherName,
1035 "size=%d", outBufSize + inBufSize + xmlSecMSCngAesGcmTagLengthInBytes);
1036 return(-1);
1037 }
1038
1039 outBuf = xmlSecBufferGetData(out) + outBufSize;
1040
1041 status = BCryptEncrypt(ctx->hKey,
1042 inBuf,
1043 (ULONG)inBufSize,
1044 &ctx->authInfo,
1045 ctx->pbIV,
1046 ctx->cbIV,
1047 outBuf,
1048 (ULONG)inBufSize,
1049 &dwCLen,
1050 0);
1051
1052 if(status != STATUS_SUCCESS) {
1053 xmlSecMSCngNtError("BCryptEncrypt", cipherName, status);
1054 return(-1);
1055 }
1056
1057 /* check if we really have encrypted the numbers of bytes that we
1058 * requested */
1059 if(dwCLen != inBufSize) {
1060 xmlSecInternalError2("BCryptEncrypt", cipherName, "size=%ld",
1061 dwCLen);
1062 return(-1);
1063 }
1064
1065 /* Now add the tag at the end of the buffer */
1066 memcpy(outBuf + inBufSize, ctx->authInfo.pbTag, xmlSecMSCngAesGcmTagLengthInBytes);
1067
1068 outLen = inBufSize + xmlSecMSCngAesGcmTagLengthInBytes;
1069
1070 } else {
1071 /* Get the tag */
1072 memcpy(ctx->authInfo.pbTag, inBuf + inBufSize - xmlSecMSCngAesGcmTagLengthInBytes,
1073 xmlSecMSCngAesGcmTagLengthInBytes);
1074
1075 /* remove the tag from the buffer */
1076 ret = xmlSecBufferRemoveTail(in, xmlSecMSCngAesGcmTagLengthInBytes);
1077 if(ret < 0) {
1078 xmlSecInternalError2("xmlSecBufferRemoveTail", cipherName,
1079 "size=%d", xmlSecMSCngAesGcmTagLengthInBytes);
1080 return(-1);
1081 }
1082
1083 inBuf = xmlSecBufferGetData(in);
1084 inBufSize = xmlSecBufferGetSize(in);
1085
1086 ret = xmlSecBufferSetMaxSize(out, outBufSize + inBufSize);
1087 if(ret < 0) {
1088 xmlSecInternalError2("xmlSecBufferSetMaxSize", cipherName,
1089 "size=%d", outBufSize + inBufSize);
1090 return(-1);
1091 }
1092
1093 outBuf = xmlSecBufferGetData(out) + outBufSize;
1094
1095 status = BCryptDecrypt(ctx->hKey,
1096 inBuf,
1097 (ULONG)inBufSize,
1098 &ctx->authInfo,
1099 ctx->pbIV,
1100 ctx->cbIV,
1101 outBuf,
1102 (ULONG)inBufSize,
1103 &dwCLen,
1104 0);
1105
1106 if(status != STATUS_SUCCESS) {
1107 xmlSecMSCngNtError("BCryptDecrypt", cipherName, status);
1108 return(-1);
1109 }
1110
1111 /* check if we really have decrypted the numbers of bytes that we
1112 * requested */
1113 if(dwCLen != inBufSize) {
1114 xmlSecInternalError2("BCryptDecrypt", cipherName, "size=%ld",
1115 dwCLen);
1116 return(-1);
1117 }
1118
1119 outLen = inBufSize;
1120 }
1121
1122 /* set correct output buffer size */
1123 ret = xmlSecBufferSetSize(out, outBufSize + outLen);
1124 if(ret < 0) {
1125 xmlSecInternalError2("xmlSecBufferSetSize", cipherName, "size=%d",
1126 outBufSize + outLen);
1127 return(-1);
1128 }
1129
1130 /* remove the processed block from input */
1131 ret = xmlSecBufferRemoveHead(in, inBufSize);
1132 if(ret < 0) {
1133 xmlSecInternalError2("xmlSecBufferRemoveHead", cipherName, "size=%d",
1134 inBufSize);
1135 return(-1);
1136 }
1137
1138 return(0);
1139 }
1140
1141 static int
xmlSecMSCngBlockCipherCtxFinal(xmlSecMSCngBlockCipherCtxPtr ctx,xmlSecBufferPtr in,xmlSecBufferPtr out,int encrypt,const xmlChar * cipherName,xmlSecTransformCtxPtr transformCtx)1142 xmlSecMSCngBlockCipherCtxFinal(xmlSecMSCngBlockCipherCtxPtr ctx,
1143 xmlSecBufferPtr in, xmlSecBufferPtr out, int encrypt,
1144 const xmlChar* cipherName, xmlSecTransformCtxPtr transformCtx)
1145 {
1146 xmlSecAssert2(ctx != NULL, -1);
1147 xmlSecAssert2(ctx->ctxInitialized != 0, -1);
1148 xmlSecAssert2(in != NULL, -1);
1149 xmlSecAssert2(out != NULL, -1);
1150 xmlSecAssert2(transformCtx != NULL, -1);
1151
1152 if(ctx->cbcMode) {
1153 return xmlSecMSCngCBCBlockCipherCtxFinal(ctx, in, out, encrypt,
1154 cipherName, transformCtx);
1155 } else {
1156 return xmlSecMSCngGCMBlockCipherCtxFinal(ctx, in, out, encrypt,
1157 cipherName, transformCtx);
1158 }
1159 }
1160
1161 static int
xmlSecMSCngBlockCipherExecute(xmlSecTransformPtr transform,int last,xmlSecTransformCtxPtr transformCtx)1162 xmlSecMSCngBlockCipherExecute(xmlSecTransformPtr transform, int last,
1163 xmlSecTransformCtxPtr transformCtx) {
1164 xmlSecMSCngBlockCipherCtxPtr ctx;
1165 xmlSecBufferPtr in, out;
1166 int ret, encrypt;
1167
1168 xmlSecAssert2(xmlSecMSCngBlockCipherCheckId(transform), -1);
1169 xmlSecAssert2((transform->operation == xmlSecTransformOperationEncrypt) || (transform->operation == xmlSecTransformOperationDecrypt), -1);
1170 xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCngBlockCipherSize), -1);
1171 xmlSecAssert2(transformCtx != NULL, -1);
1172
1173 in = &(transform->inBuf);
1174 out = &(transform->outBuf);
1175
1176 ctx = xmlSecMSCngBlockCipherGetCtx(transform);
1177 xmlSecAssert2(ctx != NULL, -1);
1178
1179 if(transform->status == xmlSecTransformStatusNone) {
1180 /* This should only be done once, before the context has been initialised */
1181 BCRYPT_INIT_AUTH_MODE_INFO(ctx->authInfo);
1182 transform->status = xmlSecTransformStatusWorking;
1183 }
1184
1185 if(transform->status == xmlSecTransformStatusWorking) {
1186
1187 encrypt = (transform->operation == xmlSecTransformOperationEncrypt) ? 1 : 0;
1188
1189 if(ctx->ctxInitialized == 0) {
1190 ret = xmlSecMSCngBlockCipherCtxInit(ctx,
1191 in,
1192 out,
1193 encrypt,
1194 last,
1195 xmlSecTransformGetName(transform),
1196 transformCtx);
1197 if(ret < 0) {
1198 xmlSecInternalError("xmlSecMSCngBlockCipherCtxInit",
1199 xmlSecTransformGetName(transform));
1200 return(-1);
1201 }
1202
1203 }
1204 if((ctx->ctxInitialized == 0) && (last != 0)) {
1205 xmlSecInvalidDataError("not enough data to initialize transform",
1206 xmlSecTransformGetName(transform));
1207 return(-1);
1208 }
1209
1210 if(ctx->ctxInitialized != 0) {
1211 ret = xmlSecMSCngBlockCipherCtxUpdate(ctx, in, out,
1212 encrypt,
1213 last,
1214 xmlSecTransformGetName(transform), transformCtx);
1215 if(ret < 0) {
1216 xmlSecInternalError("xmlSecMSCngBlockCipherCtxUpdate",
1217 xmlSecTransformGetName(transform));
1218 return(-1);
1219 }
1220 }
1221
1222 if(last) {
1223 ret = xmlSecMSCngBlockCipherCtxFinal(ctx, in, out,
1224 encrypt,
1225 xmlSecTransformGetName(transform), transformCtx);
1226
1227 if(ret < 0) {
1228 xmlSecInternalError("xmlSecMSCngBlockCipherCtxFinal",
1229 xmlSecTransformGetName(transform));
1230 return(-1);
1231 }
1232
1233 transform->status = xmlSecTransformStatusFinished;
1234 }
1235 } else if(transform->status == xmlSecTransformStatusFinished) {
1236 /* the only way we can get here is if there is no input */
1237 xmlSecAssert2(xmlSecBufferGetSize(in) == 0, -1);
1238 } else if(transform->status == xmlSecTransformStatusNone) {
1239 /* the only way we can get here is if there is not enough data in the input */
1240 xmlSecAssert2(last == 0, -1);
1241 } else {
1242 xmlSecInvalidTransfromStatusError(transform);
1243 return(-1);
1244 }
1245
1246 return(0);
1247 }
1248
1249 #ifndef XMLSEC_NO_AES
1250
1251 static xmlSecTransformKlass xmlSecMSCngAes128CbcKlass = {
1252 /* klass/object sizes */
1253 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
1254 xmlSecMSCngBlockCipherSize, /* xmlSecSize objSize */
1255
1256 xmlSecNameAes128Cbc, /* const xmlChar* name; */
1257 xmlSecHrefAes128Cbc, /* const xmlChar* href; */
1258 xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
1259
1260 xmlSecMSCngBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
1261 xmlSecMSCngBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
1262 NULL, /* xmlSecTransformNodeReadMethod readNode; */
1263 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
1264 xmlSecMSCngBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
1265 xmlSecMSCngBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
1266 NULL, /* xmlSecTransformValidateMethod validate; */
1267 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
1268 xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
1269 xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
1270 NULL, /* xmlSecTransformPushXmlMethod pushXml; */
1271 NULL, /* xmlSecTransformPopXmlMethod popXml; */
1272 xmlSecMSCngBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
1273
1274 NULL, /* void* reserved0; */
1275 NULL, /* void* reserved1; */
1276 };
1277
1278 /**
1279 * xmlSecMSCngTransformAes128CbcGetKlass:
1280 *
1281 * AES 128 CBC encryption transform klass.
1282 *
1283 * Returns: pointer to AES 128 CBC encryption transform.
1284 */
1285 xmlSecTransformId
xmlSecMSCngTransformAes128CbcGetKlass(void)1286 xmlSecMSCngTransformAes128CbcGetKlass(void) {
1287 return(&xmlSecMSCngAes128CbcKlass);
1288 }
1289
1290 static xmlSecTransformKlass xmlSecMSCngAes192CbcKlass = {
1291 /* klass/object sizes */
1292 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
1293 xmlSecMSCngBlockCipherSize, /* xmlSecSize objSize */
1294
1295 xmlSecNameAes192Cbc, /* const xmlChar* name; */
1296 xmlSecHrefAes192Cbc, /* const xmlChar* href; */
1297 xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
1298
1299 xmlSecMSCngBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
1300 xmlSecMSCngBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
1301 NULL, /* xmlSecTransformNodeReadMethod readNode; */
1302 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
1303 xmlSecMSCngBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
1304 xmlSecMSCngBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
1305 NULL, /* xmlSecTransformValidateMethod validate; */
1306 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
1307 xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
1308 xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
1309 NULL, /* xmlSecTransformPushXmlMethod pushXml; */
1310 NULL, /* xmlSecTransformPopXmlMethod popXml; */
1311 xmlSecMSCngBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
1312
1313 NULL, /* void* reserved0; */
1314 NULL, /* void* reserved1; */
1315 };
1316
1317 /**
1318 * xmlSecMSCngTransformAes192CbcGetKlass:
1319 *
1320 * AES 192 CBC encryption transform klass.
1321 *
1322 * Returns: pointer to AES 192 CBC encryption transform.
1323 */
1324 xmlSecTransformId
xmlSecMSCngTransformAes192CbcGetKlass(void)1325 xmlSecMSCngTransformAes192CbcGetKlass(void) {
1326 return(&xmlSecMSCngAes192CbcKlass);
1327 }
1328
1329 static xmlSecTransformKlass xmlSecMSCngAes256CbcKlass = {
1330 /* klass/object sizes */
1331 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
1332 xmlSecMSCngBlockCipherSize, /* xmlSecSize objSize */
1333
1334 xmlSecNameAes256Cbc, /* const xmlChar* name; */
1335 xmlSecHrefAes256Cbc, /* const xmlChar* href; */
1336 xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
1337
1338 xmlSecMSCngBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
1339 xmlSecMSCngBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
1340 NULL, /* xmlSecTransformNodeReadMethod readNode; */
1341 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
1342 xmlSecMSCngBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
1343 xmlSecMSCngBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
1344 NULL, /* xmlSecTransformValidateMethod validate; */
1345 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
1346 xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
1347 xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
1348 NULL, /* xmlSecTransformPushXmlMethod pushXml; */
1349 NULL, /* xmlSecTransformPopXmlMethod popXml; */
1350 xmlSecMSCngBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
1351
1352 NULL, /* void* reserved0; */
1353 NULL, /* void* reserved1; */
1354 };
1355
1356 /**
1357 * xmlSecMSCngTransformAes256CbcGetKlass:
1358 *
1359 * AES 256 CBC encryption transform klass.
1360 *
1361 * Returns: pointer to AES 256 CBC encryption transform.
1362 */
1363 xmlSecTransformId
xmlSecMSCngTransformAes256CbcGetKlass(void)1364 xmlSecMSCngTransformAes256CbcGetKlass(void) {
1365 return(&xmlSecMSCngAes256CbcKlass);
1366 }
1367
1368 static xmlSecTransformKlass xmlSecMSCngAes128GcmKlass = {
1369 /* klass/object sizes */
1370 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
1371 xmlSecMSCngBlockCipherSize, /* xmlSecSize objSize */
1372
1373 xmlSecNameAes128Gcm, /* const xmlChar* name; */
1374 xmlSecHrefAes128Gcm, /* const xmlChar* href; */
1375 xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
1376
1377 xmlSecMSCngBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
1378 xmlSecMSCngBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
1379 NULL, /* xmlSecTransformNodeReadMethod readNode; */
1380 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
1381 xmlSecMSCngBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
1382 xmlSecMSCngBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
1383 NULL, /* xmlSecTransformValidateMethod validate; */
1384 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
1385 xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
1386 xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
1387 NULL, /* xmlSecTransformPushXmlMethod pushXml; */
1388 NULL, /* xmlSecTransformPopXmlMethod popXml; */
1389 xmlSecMSCngBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
1390
1391 NULL, /* void* reserved0; */
1392 NULL, /* void* reserved1; */
1393 };
1394
1395 /**
1396 * xmlSecMSCngTransformAes128GcmGetKlass:
1397 *
1398 * AES 128 GCM encryption transform klass.
1399 *
1400 * Returns: pointer to AES 128 GCM encryption transform.
1401 */
1402 xmlSecTransformId
xmlSecMSCngTransformAes128GcmGetKlass(void)1403 xmlSecMSCngTransformAes128GcmGetKlass(void) {
1404 return(&xmlSecMSCngAes128GcmKlass);
1405 }
1406
1407 static xmlSecTransformKlass xmlSecMSCngAes192GcmKlass = {
1408 /* klass/object sizes */
1409 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
1410 xmlSecMSCngBlockCipherSize, /* xmlSecSize objSize */
1411
1412 xmlSecNameAes192Gcm, /* const xmlChar* name; */
1413 xmlSecHrefAes192Gcm, /* const xmlChar* href; */
1414 xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
1415
1416 xmlSecMSCngBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
1417 xmlSecMSCngBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
1418 NULL, /* xmlSecTransformNodeReadMethod readNode; */
1419 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
1420 xmlSecMSCngBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
1421 xmlSecMSCngBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
1422 NULL, /* xmlSecTransformValidateMethod validate; */
1423 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
1424 xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
1425 xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
1426 NULL, /* xmlSecTransformPushXmlMethod pushXml; */
1427 NULL, /* xmlSecTransformPopXmlMethod popXml; */
1428 xmlSecMSCngBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
1429
1430 NULL, /* void* reserved0; */
1431 NULL, /* void* reserved1; */
1432 };
1433
1434 /**
1435 * xmlSecMSCngTransformAes192GcmGetKlass:
1436 *
1437 * AES 192 GCM encryption transform klass.
1438 *
1439 * Returns: pointer to AES 192 GCM encryption transform.
1440 */
1441 xmlSecTransformId
xmlSecMSCngTransformAes192GcmGetKlass(void)1442 xmlSecMSCngTransformAes192GcmGetKlass(void) {
1443 return(&xmlSecMSCngAes192GcmKlass);
1444 }
1445
1446
1447 static xmlSecTransformKlass xmlSecMSCngAes256GcmKlass = {
1448 /* klass/object sizes */
1449 sizeof(xmlSecTransformKlass), /* xmlSecSize klassSize */
1450 xmlSecMSCngBlockCipherSize, /* xmlSecSize objSize */
1451
1452 xmlSecNameAes256Gcm, /* const xmlChar* name; */
1453 xmlSecHrefAes256Gcm, /* const xmlChar* href; */
1454 xmlSecTransformUsageEncryptionMethod, /* xmlSecAlgorithmUsage usage; */
1455
1456 xmlSecMSCngBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
1457 xmlSecMSCngBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
1458 NULL, /* xmlSecTransformNodeReadMethod readNode; */
1459 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
1460 xmlSecMSCngBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
1461 xmlSecMSCngBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
1462 NULL, /* xmlSecTransformValidateMethod validate; */
1463 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
1464 xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
1465 xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
1466 NULL, /* xmlSecTransformPushXmlMethod pushXml; */
1467 NULL, /* xmlSecTransformPopXmlMethod popXml; */
1468 xmlSecMSCngBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
1469
1470 NULL, /* void* reserved0; */
1471 NULL, /* void* reserved1; */
1472 };
1473
1474 /**
1475 * xmlSecMSCngTransformAes256GcmGetKlass:
1476 *
1477 * AES 256 GCM encryption transform klass.
1478 *
1479 * Returns: pointer to AES 256 GCM encryption transform.
1480 */
1481 xmlSecTransformId
xmlSecMSCngTransformAes256GcmGetKlass(void)1482 xmlSecMSCngTransformAes256GcmGetKlass(void) {
1483 return(&xmlSecMSCngAes256GcmKlass);
1484 }
1485
1486 #endif /* XMLSEC_NO_AES */
1487
1488 #ifndef XMLSEC_NO_DES
1489
1490 static xmlSecTransformKlass xmlSecMSCngDes3CbcKlass = {
1491 /* klass/object sizes */
1492 sizeof(xmlSecTransformKlass), /* size_t klassSize */
1493 xmlSecMSCngBlockCipherSize, /* size_t objSize */
1494
1495 xmlSecNameDes3Cbc, /* const xmlChar* name; */
1496 xmlSecHrefDes3Cbc, /* const xmlChar* href; */
1497 xmlSecTransformUsageEncryptionMethod,/* xmlSecAlgorithmUsage usage; */
1498
1499 xmlSecMSCngBlockCipherInitialize, /* xmlSecTransformInitializeMethod initialize; */
1500 xmlSecMSCngBlockCipherFinalize, /* xmlSecTransformFinalizeMethod finalize; */
1501 NULL, /* xmlSecTransformNodeReadMethod readNode; */
1502 NULL, /* xmlSecTransformNodeWriteMethod writeNode; */
1503 xmlSecMSCngBlockCipherSetKeyReq, /* xmlSecTransformSetKeyMethod setKeyReq; */
1504 xmlSecMSCngBlockCipherSetKey, /* xmlSecTransformSetKeyMethod setKey; */
1505 NULL, /* xmlSecTransformValidateMethod validate; */
1506 xmlSecTransformDefaultGetDataType, /* xmlSecTransformGetDataTypeMethod getDataType; */
1507 xmlSecTransformDefaultPushBin, /* xmlSecTransformPushBinMethod pushBin; */
1508 xmlSecTransformDefaultPopBin, /* xmlSecTransformPopBinMethod popBin; */
1509 NULL, /* xmlSecTransformPushXmlMethod pushXml; */
1510 NULL, /* xmlSecTransformPopXmlMethod popXml; */
1511 xmlSecMSCngBlockCipherExecute, /* xmlSecTransformExecuteMethod execute; */
1512
1513 NULL, /* void* reserved0; */
1514 NULL, /* void* reserved1; */
1515 };
1516
1517 /**
1518 * xmlSecMSCngTransformDes3CbcGetKlass:
1519 *
1520 * Triple DES CBC encryption transform klass.
1521 *
1522 * Returns: pointer to Triple DES encryption transform.
1523 */
1524 xmlSecTransformId
xmlSecMSCngTransformDes3CbcGetKlass(void)1525 xmlSecMSCngTransformDes3CbcGetKlass(void) {
1526 return(&xmlSecMSCngDes3CbcKlass);
1527 }
1528
1529 #endif /* XMLSEC_NO_DES */
1530