ReactOS 0.4.17-dev-1005-g171e1de
dlkey.c
Go to the documentation of this file.
1//
2// dlkey.c Dlkey functions
3//
4// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5//
6//
7
8#include "precomp.h"
9
13{
14 PVOID p;
15 SIZE_T cb;
17
19
21
22 if ( p==NULL )
23 {
24 goto cleanup;
25 }
26
28
30 return res;
31}
32
33VOID
36{
37 SYMCRYPT_CHECK_MAGIC( pkObj );
38 SymCryptDlkeyWipe( pkObj );
39 SymCryptCallbackFree( pkObj );
40}
41
45{
46 // Always allocate memory for large private keys
48}
49
56{
57 PSYMCRYPT_DLKEY pkRes = NULL;
59
62 UNREFERENCED_PARAMETER( cbBuffer ); // only referenced in above ASSERTs...
64
65 pkRes = (PSYMCRYPT_DLKEY) pbBuffer;
66
67 // DLKEY parameters
68 pkRes->fAlgorithmInfo = 0;
69 pkRes->pDlgroup = pDlgroup;
70 pkRes->fHasPrivateKey = FALSE;
71 pkRes->fPrivateModQ = FALSE; // This will be properly set during generate or setvalue
72 pkRes->nBitsPriv = pDlgroup->nDefaultBitsPriv;
73
74 // Create SymCrypt objects
75 pbBuffer += sizeof(SYMCRYPT_DLKEY);
76
77 pkRes->pePublicKey = SymCryptModElementCreate( pbBuffer, cbModElement, pDlgroup->pmP );
78 if (pkRes->pePublicKey == NULL)
79 {
80 goto cleanup;
81 }
82 pbBuffer += cbModElement;
83
84 //
85 // **** Always defer the creation of the private key until the key generation or
86 // set value.
87 //
88 // In place of the pbPrivate pointer store the pointer to the allocated buffer.
89 //
90 pkRes->pbPrivate = pbBuffer;
91 pkRes->piPrivateKey = NULL;
92
93 // Setting the magic
94 SYMCRYPT_SET_MAGIC( pkRes );
95
97 return pkRes;
98}
99
100VOID
103{
104 SymCryptWipe( (PBYTE) pkDst, SymCryptSizeofDlkeyFromDlgroup(pkDst->pDlgroup) );
105}
106
107VOID
111 _Out_ PSYMCRYPT_DLKEY pkDst )
112{
113 PCSYMCRYPT_DLGROUP pDlgroup = pkSrc->pDlgroup;
114
115 //
116 // in-place copy is somewhat common...
117 //
118 if( pkSrc != pkDst )
119 {
120 pkDst->fAlgorithmInfo = pkSrc->fAlgorithmInfo;
121 pkDst->fHasPrivateKey = pkSrc->fHasPrivateKey;
122 pkDst->fPrivateModQ = pkSrc->fPrivateModQ;
123 pkDst->nBitsPriv = pkSrc->nBitsPriv;
124
125 // Copy the public key
126 SymCryptModElementCopy( pDlgroup->pmP, pkSrc->pePublicKey, pkDst->pePublicKey );
127
128 // Copy the private key
129 SymCryptIntCopy( pkSrc->piPrivateKey, pkDst->piPrivateKey );
130 }
131}
132
133
134// DLKEY specific functions
135
139{
140 if( nBitsPriv > pkDlkey->pDlgroup->nBitsOfQ ||
141 nBitsPriv < pkDlkey->pDlgroup->nMinBitsPriv ||
142 flags != 0 )
143 {
144 return SYMCRYPT_INVALID_ARGUMENT;
145 }
146
147 pkDlkey->nBitsPriv = nBitsPriv;
148 return SYMCRYPT_NO_ERROR;
149}
150
154{
155 return pkDlkey->pDlgroup;
156}
157
158UINT32
161{
162 return pkDlkey->pDlgroup->cbPrimeP;
163}
164
165UINT32
168{
169 PCSYMCRYPT_DLGROUP pDlgroup = pkDlkey->pDlgroup;
170
171 if (pkDlkey->fPrivateModQ)
172 {
173 if (pDlgroup->fHasPrimeQ)
174 {
175 if (pkDlkey->nBitsPriv != pDlgroup->nBitsOfQ)
176 {
177 return (pkDlkey->nBitsPriv + 7) / 8;
178 }
179 else
180 {
181 return pDlgroup->cbPrimeQ;
182 }
183 }
184 else
185 {
186 return pDlgroup->cbPrimeP; // Somehow the group has no prime Q but the key was set with prime Q, return the safe option
187 }
188 }
189 else
190 {
191 return pDlgroup->cbPrimeP;
192 }
193}
194
198{
199 return pkDlkey->fHasPrivateKey;
200}
201
202#define SYMCRYPT_FLAG_DLKEY_PUBLIC_KEY_ORDER_VALIDATION (0x1)
203
207 _In_ PCSYMCRYPT_DLKEY pkDlkey,
211{
212 PCSYMCRYPT_DLGROUP pDlgroup = pkDlkey->pDlgroup;
213
215 PSYMCRYPT_MODELEMENT peTmpPublicKeyExpQ = NULL;
217
220
221 // Check if Public key is 0
222 if ( SymCryptModElementIsZero( pDlgroup->pmP, pkDlkey->pePublicKey ) )
223 {
224 return SYMCRYPT_INVALID_ARGUMENT;
225 }
226
227 peTmp = SymCryptModElementCreate( pbScratch, cbModElement, pDlgroup->pmP);
228 pbScratch += cbModElement;
230
231 // Check if Public key is P-1
232 SymCryptModElementSetValueNegUint32( 1, pDlgroup->pmP, peTmp, pbScratch, cbScratch );
233 if ( SymCryptModElementIsEqual( pDlgroup->pmP, pkDlkey->pePublicKey, peTmp ) )
234 {
235 return SYMCRYPT_INVALID_ARGUMENT;
236 }
237
238 // Check if Public key is 1 (do this check second as we may reuse 1 element in next check)
239 SymCryptModElementSetValueUint32( 1, pDlgroup->pmP, peTmp, pbScratch, cbScratch );
240 if ( SymCryptModElementIsEqual( pDlgroup->pmP, pkDlkey->pePublicKey, peTmp ) )
241 {
242 return SYMCRYPT_INVALID_ARGUMENT;
243 }
244
245 // Perform validation that Public key is in a subgroup of order Q.
247 {
248 peTmpPublicKeyExpQ = SymCryptModElementCreate( pbScratch, cbModElement, pDlgroup->pmP);
249 pbScratch += cbModElement;
251
252 // Ensure that Q is specified in the Dlgroup
253 if ( !pDlgroup->fHasPrimeQ )
254 {
255 return SYMCRYPT_INVALID_ARGUMENT;
256 }
257
258 // Calculate peTmpPublicKeyExpQ = (Public key)^Q
260 pDlgroup->pmP,
261 pkDlkey->pePublicKey,
263 pDlgroup->nBitsOfQ,
264 SYMCRYPT_FLAG_DATA_PUBLIC, // No need for side-channel safety for public key validation
265 peTmpPublicKeyExpQ,
266 pbScratch,
267 cbScratch );
268
269 // Ensure (Public key)^Q == 1 mod P
270 if ( !SymCryptModElementIsEqual( pDlgroup->pmP, peTmpPublicKeyExpQ, peTmp ) )
271 {
272 return SYMCRYPT_INVALID_ARGUMENT;
273 }
274 }
275
276 return SYMCRYPT_NO_ERROR;
277}
278
279#define DLKEY_GEN_RANDOM_GENERIC_LIMIT (1000)
280
285 _Inout_ PSYMCRYPT_DLKEY pkDlkey )
286{
287 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
288 PBYTE pbScratch = NULL;
289 SIZE_T cbScratch = 0;
290 PBYTE pbScratchInternal = NULL;
291 SIZE_T cbScratchInternal = 0;
292
293 PCSYMCRYPT_DLGROUP pDlgroup = pkDlkey->pDlgroup;
294
295 PSYMCRYPT_MODELEMENT pePrivateKey = NULL;
296 UINT32 cbPrivateKey = 0;
297
298 PSYMCRYPT_MODULUS pmPriv = NULL;
299 UINT32 nDigitsPriv = 0;
300 UINT32 nBitsPriv = 0;
301 UINT32 fFlagsForModSetRandom = 0;
302
303 BOOLEAN useModSetRandom = TRUE;
304 UINT32 nBytesPriv = 0;
305 UINT32 dwShiftBits;
306 BYTE privMask;
307 UINT32 cntr;
308
311
312 // Ensure caller has specified what algorithm(s) the key will be used with
314 // Make sure only allowed flags are specified
315 UINT32 allowedFlags = SYMCRYPT_FLAG_DLKEY_GEN_MODP | SYMCRYPT_FLAG_KEY_NO_FIPS | algorithmFlags;
316
317 if ( ( ( flags & ~allowedFlags ) != 0 ) ||
318 ( ( flags & algorithmFlags ) == 0 ) )
319 {
320 scError = SYMCRYPT_INVALID_ARGUMENT;
321 goto cleanup;
322 }
323
324 // Extra sanity checks when running with FIPS
325 // Either Dlgroup is named SafePrime group and key is for DH,
326 // or Dlgroup is not named SafePrime group and key is for DSA
327 if ( ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 ) &&
328 ( (pDlgroup->isSafePrimeGroup && (flags & SYMCRYPT_FLAG_DLKEY_DSA)) ||
329 (!(pDlgroup->isSafePrimeGroup) && (flags & SYMCRYPT_FLAG_DLKEY_DH)) ) )
330 {
331 scError = SYMCRYPT_INVALID_ARGUMENT;
332 goto cleanup;
333 }
334
335 pkDlkey->fPrivateModQ = (((flags & SYMCRYPT_FLAG_DLKEY_GEN_MODP)==0) && (pDlgroup->fHasPrimeQ));
336
337 if (pkDlkey->fPrivateModQ)
338 {
339 pmPriv = pDlgroup->pmQ;
340 nDigitsPriv = pDlgroup->nDigitsOfQ;
341 nBitsPriv = pDlgroup->nBitsOfQ;
343
344 if ( pDlgroup->isSafePrimeGroup && (pkDlkey->nBitsPriv != pDlgroup->nBitsOfQ) )
345 {
346 useModSetRandom = FALSE;
347 SYMCRYPT_ASSERT( pkDlkey->nBitsPriv < pDlgroup->nBitsOfQ ); // 2^nBitsPriv < Q
348
349 nBitsPriv = pkDlkey->nBitsPriv; // 1 to (2^nBitsPriv)-1
350 nBytesPriv = (pkDlkey->nBitsPriv + 7) / 8;
351 }
352 }
353 else
354 {
355 // We perform Private key range validation by construction
356 // The Private key is constructed in the range [1,min(2^nBitsPriv,Q)-1] precisely when pkDlkey->fPrivateModQ
357 if ( (flags & SYMCRYPT_FLAG_KEY_NO_FIPS) == 0 )
358 {
359 scError = SYMCRYPT_INVALID_ARGUMENT;
360 goto cleanup;
361 }
362
363 pmPriv = pDlgroup->pmP;
364 nDigitsPriv = pDlgroup->nDigitsOfP;
365 nBitsPriv = pDlgroup->nBitsOfP;
366 fFlagsForModSetRandom = SYMCRYPT_FLAG_MODRANDOM_ALLOW_ONE; // 1 to P-2
367 }
368
369 cbPrivateKey = SymCryptSizeofModElementFromModulus( pmPriv );
370
371 //
372 // From symcrypt_internal.h we have:
373 // - sizeof results are upper bounded by 2^19
374 // - SYMCRYPT_SCRATCH_BYTES results are upper bounded by 2^27 (including RSA and ECURVE)
375 // Thus the following calculation does not overflow cbScratch.
376 //
379 pbScratch = SymCryptCallbackAlloc( cbScratch );
380 if (pbScratch == NULL)
381 {
382 scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
383 goto cleanup;
384 }
385
386 // Create the private key integer
387 pkDlkey->piPrivateKey = SymCryptIntCreate( pkDlkey->pbPrivate, SymCryptSizeofIntFromDigits(nDigitsPriv), nDigitsPriv );
388
389 if (useModSetRandom)
390 {
391 // Create the private key modelement
392 pePrivateKey = SymCryptModElementCreate( pbScratch, cbPrivateKey, pmPriv );
393 pbScratchInternal = pbScratch + cbPrivateKey;
394 cbScratchInternal = cbScratch - cbPrivateKey;
395
396 // Set a modelement from 1 to q-1 (or 1 to p-2)
398 pmPriv,
399 pePrivateKey,
400 fFlagsForModSetRandom,
401 pbScratchInternal,
402 cbScratchInternal );
403
404 // Set the private key
406 pmPriv,
407 pePrivateKey,
408 pkDlkey->piPrivateKey,
409 pbScratchInternal,
410 cbScratchInternal );
411 }
412 else
413 {
414 // Set private key from 1 to (2^nBitsPriv)-1
415 // Wipe any bytes we won't fill with random
416 SymCryptWipe( pbScratch + nBytesPriv, (nDigitsPriv * SYMCRYPT_FDEF_DIGIT_SIZE) - nBytesPriv );
417
418 dwShiftBits = (0u-nBitsPriv) & 7;
419 privMask = (BYTE)(0xff >> dwShiftBits);
420
421 for(cntr=0; cntr<DLKEY_GEN_RANDOM_GENERIC_LIMIT; cntr++)
422 {
423 // Try random values until we get one we like
424 SymCryptCallbackRandom( pbScratch, nBytesPriv );
425
426 pbScratch[nBytesPriv-1] &= privMask;
427
428 // If non-zero we have a value in range [1, (2^nBitsPriv)-1]
429 if( !SymCryptFdefRawIsEqualUint32( (PCUINT32)pbScratch, nDigitsPriv, 0 ) )
430 {
431 break;
432 }
433 }
434
436 {
437 SymCryptFatal( 'rndl' );
438 }
439
440 scError = SymCryptIntSetValue( pbScratch, nBytesPriv, SYMCRYPT_NUMBER_FORMAT_LSB_FIRST, pkDlkey->piPrivateKey );
441 if ( scError != SYMCRYPT_NO_ERROR )
442 {
443 goto cleanup;
444 }
445 }
446
447 // Calculate the public key
449 pDlgroup->pmP,
450 pDlgroup->peG,
451 pkDlkey->piPrivateKey,
452 nBitsPriv,
453 0, // Side-channel safe
454 pkDlkey->pePublicKey,
455 pbScratch, // We can overwrite pePrivateKey now
456 cbScratch );
457
458 // Perform range validation on generated Public key.
459 if ( (flags & SYMCRYPT_FLAG_KEY_NO_FIPS) == 0 )
460 {
461 // Perform Public key validation.
462 // Always perform range validation, and validation that Public key is in subgroup of order Q
464 pkDlkey,
466 pbScratch,
467 cbScratch );
468 if ( scError != SYMCRYPT_NO_ERROR )
469 {
470 goto cleanup;
471 }
472 }
473
474 // Set the fHasPrivateKey flag
475 pkDlkey->fHasPrivateKey = TRUE;
476
477 pkDlkey->fAlgorithmInfo = flags; // We want to track all of the flags in the Dlkey
478
479 if ( (flags & SYMCRYPT_FLAG_KEY_NO_FIPS) == 0 )
480 {
481 if( ( flags & SYMCRYPT_FLAG_DLKEY_DSA ) != 0 )
482 {
483 // Ensure DSA algorithm selftest is run before first use of DSA algorithm
487
488 // Run PCT eagerly as the key can only be used for DSA - there is no value in deferring
491 pkDlkey,
493 }
494
495 if( ( flags & SYMCRYPT_FLAG_DLKEY_DH ) != 0 )
496 {
497 // Ensure we have run the algorithm selftest at least once.
501
502 // Run PCT eagerly as the key can only be used for DH
503
504 // DH PCT per SP80056a-rev3 5.6.2.1.4 b)
505 // Recompute the public key from the private key
506 // Option a) appears to be explicitly overruled by 140-3 IG
507
508 // Calculate the public key from the private key in scratch
509 pbScratchInternal = pbScratch;
510 cbScratchInternal = cbScratch;
511
512 peTmp = SymCryptModElementCreate( pbScratchInternal, cbModElement, pDlgroup->pmP );
513 pbScratchInternal += cbModElement;
514 cbScratchInternal -= cbModElement;
515
517 pDlgroup->pmP,
518 pDlgroup->peG,
519 pkDlkey->piPrivateKey,
520 nBitsPriv, // This is either bits of P, Q, or some caller-defined value i.e. public values
521 0, // Side-channel safe
522 peTmp,
523 pbScratchInternal,
524 cbScratchInternal );
525
526 SYMCRYPT_FIPS_ASSERT( SymCryptModElementIsEqual(pDlgroup->pmP, peTmp, pkDlkey->pePublicKey) );
527 }
528 }
529
530cleanup:
531 if (pbScratch!=NULL)
532 {
533 SymCryptWipe( pbScratch, cbScratch );
534 SymCryptCallbackFree( pbScratch );
535 }
536 return scError;
537}
538
542 _In_reads_bytes_( cbPrivateKey ) PCBYTE pbPrivateKey,
543 SIZE_T cbPrivateKey,
544 _In_reads_bytes_( cbPublicKey ) PCBYTE pbPublicKey,
545 SIZE_T cbPublicKey,
546 SYMCRYPT_NUMBER_FORMAT numFormat,
548 _Inout_ PSYMCRYPT_DLKEY pkDlkey )
549{
550 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
551 PBYTE pbScratch = NULL;
552 UINT32 cbScratch = 0;
553 PBYTE pbScratchInternal = NULL;
554 UINT32 cbScratchInternal = 0;
555
556 PCSYMCRYPT_DLGROUP pDlgroup = pkDlkey->pDlgroup;
557
558 UINT32 nDigitsPriv = 0;
559 UINT32 nBitsPriv = 0;
560
564
565 if ( ((pbPrivateKey==NULL) && (cbPrivateKey!=0)) ||
566 ((pbPublicKey==NULL) && (cbPublicKey!=0)) ||
567 ((pbPrivateKey==NULL) && (pbPublicKey==NULL)) )
568 {
569 scError = SYMCRYPT_INVALID_ARGUMENT;
570 goto cleanup;
571 }
572
573 // Ensure caller has specified what algorithm(s) the key will be used with
575 // Make sure only allowed flags are specified
577
578 if ( ( ( flags & ~allowedFlags ) != 0 ) ||
579 ( ( flags & algorithmFlags ) == 0 ) )
580 {
581 scError = SYMCRYPT_INVALID_ARGUMENT;
582 goto cleanup;
583 }
584
585 // Extra sanity checks when running with FIPS
586 // Either Dlgroup is named SafePrime group and key is for DH,
587 // or Dlgroup is not named SafePrime group and key is for DSA
588 if ( ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 ) &&
589 ( (pDlgroup->isSafePrimeGroup && (flags & SYMCRYPT_FLAG_DLKEY_DSA)) ||
590 (!(pDlgroup->isSafePrimeGroup) && (flags & SYMCRYPT_FLAG_DLKEY_DH)) ) )
591 {
592 scError = SYMCRYPT_INVALID_ARGUMENT;
593 goto cleanup;
594 }
595
596 // Check that minimal validation flag only specified with no fips
597 if ( ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 ) &&
599 {
600 scError = SYMCRYPT_INVALID_ARGUMENT;
601 goto cleanup;
602 }
603
604 if ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) != 0 )
605 {
606 fValidatePublicKeyOrder = 0;
607 }
608
609 //
610 // From symcrypt_internal.h we have:
611 // - sizeof results are upper bounded by 2^19
612 // - SYMCRYPT_SCRATCH_BYTES results are upper bounded by 2^27 (including RSA and ECURVE)
613 // Thus the following calculation does not overflow cbScratch.
614 //
617 pbScratch = SymCryptCallbackAlloc( cbScratch );
618 if (pbScratch == NULL)
619 {
620 scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
621 goto cleanup;
622 }
623
624 if ( pbPrivateKey != NULL )
625 {
626 //
627 // Check the size of the imported private key to detect if it is mod P or mod Q
628 // If the group does not have a Q assume that the imported key is modulo P as
629 // it wouldn't help us assume otherwise (the bitsize of the private key should be kept
630 // secret from SC attacks).
631 // If the private key has had some non-default value set for nBitsPriv then the caller
632 // has explicitly opted in to more stringent range checking.
633 //
634 pkDlkey->fPrivateModQ = ( (pDlgroup->fHasPrimeQ) &&
635 ((cbPrivateKey < pDlgroup->cbPrimeQ) ||
636 ((cbPrivateKey == pDlgroup->cbPrimeQ) && (pDlgroup->cbPrimeQ < pDlgroup->cbPrimeP)) ||
637 (pkDlkey->nBitsPriv != pDlgroup->nDefaultBitsPriv)) );
638
639 if ( pkDlkey->fPrivateModQ )
640 {
641 nDigitsPriv = pDlgroup->nDigitsOfQ;
642 nBitsPriv = pDlgroup->nBitsOfQ;
643
644 if ( pDlgroup->isSafePrimeGroup )
645 {
646 nBitsPriv = pkDlkey->nBitsPriv;
647 }
648 }
649 else
650 {
651 nDigitsPriv = pDlgroup->nDigitsOfP;
652 nBitsPriv = pDlgroup->nBitsOfP;
653 }
654
655 pkDlkey->piPrivateKey = SymCryptIntCreate( pkDlkey->pbPrivate, SymCryptSizeofIntFromDigits(nDigitsPriv), nDigitsPriv );
656
657 scError = SymCryptIntSetValue(
658 pbPrivateKey,
659 cbPrivateKey,
660 numFormat,
661 pkDlkey->piPrivateKey );
662 if ( scError != SYMCRYPT_NO_ERROR )
663 {
664 goto cleanup;
665 }
666
667 // Perform range validation on imported Private key.
668 // Check if Private key is 0 - perform unconditionally as it is cheap
669 // and it never makes sense for private key to be 0 intentionally
670 if ( SymCryptIntIsEqualUint32( pkDlkey->piPrivateKey, 0 ) )
671 {
672 scError = SYMCRYPT_INVALID_ARGUMENT;
673 goto cleanup;
674 }
675
676 // Continue range validation on imported Private key.
677 if ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 )
678 {
679 // Ensure that Q is specified in the Dlgroup
680 if ( !pDlgroup->fHasPrimeQ )
681 {
682 scError = SYMCRYPT_INVALID_ARGUMENT;
683 goto cleanup;
684 }
685
686 // If nBitsPriv is specified, check if Private key is greater than or equal to 2^nBitsPriv
687 // Otherwise, check if Private key is greater than or equal to Q
688 if ( ( ( (nBitsPriv < pDlgroup->nBitsOfQ) &&
689 SymCryptIntBitsizeOfValue( pkDlkey->piPrivateKey ) > nBitsPriv ) ) ||
690 ( (nBitsPriv >= pDlgroup->nBitsOfQ) &&
691 !SymCryptIntIsLessThan( pkDlkey->piPrivateKey, SymCryptIntFromModulus( pDlgroup->pmQ ) ) ) )
692 {
693 scError = SYMCRYPT_INVALID_ARGUMENT;
694 goto cleanup;
695 }
696 }
697
698 pkDlkey->fHasPrivateKey = TRUE;
699 }
700
701 if ( pbPublicKey != NULL )
702 {
704 pbPublicKey,
705 cbPublicKey,
706 numFormat,
707 pDlgroup->pmP,
708 pkDlkey->pePublicKey,
709 pbScratch,
710 cbScratch );
711 if ( scError != SYMCRYPT_NO_ERROR )
712 {
713 goto cleanup;
714 }
715
716 // Perform range validation on imported Public key.
718 {
719 // Perform Public key validation.
720 // Always perform range validation
721 // May also perform validation that Public key is in subgroup of order Q, depending on flags
723 pkDlkey,
724 fValidatePublicKeyOrder,
725 pbScratch,
726 cbScratch );
727 if ( scError != SYMCRYPT_NO_ERROR )
728 {
729 goto cleanup;
730 }
731 }
732 }
733
734 // Calculating the public key if no key was provided
735 // or if needed for keypair regeneration validation
736 if ( (pbPublicKey==NULL) ||
737 ( ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 ) &&
738 (pbPrivateKey!=NULL) && (pbPublicKey!=NULL) ) )
739 {
740 // Calculate the public key from the private key
741 pbScratchInternal = pbScratch;
742 cbScratchInternal = cbScratch;
743
744 // By default calculate the public key directly where it will be persisted
745 peTmp = pkDlkey->pePublicKey;
746
747 if ( pbPublicKey != NULL )
748 {
749 // If doing regeneration validation calculate the public key in scratch
750 peTmp = SymCryptModElementCreate( pbScratchInternal, cbModElement, pDlgroup->pmP);
751 pbScratchInternal += cbModElement;
752 cbScratchInternal -= cbModElement;
753 }
754
756 pDlgroup->pmP,
757 pDlgroup->peG,
758 pkDlkey->piPrivateKey,
759 nBitsPriv, // This is either bits of P, Q, or some caller-defined value i.e. public values
760 0, // Side-channel safe
761 peTmp,
762 pbScratchInternal,
763 cbScratchInternal );
764
765 if ( pbPublicKey != NULL )
766 {
767 if ( !SymCryptModElementIsEqual(pDlgroup->pmP, peTmp, pkDlkey->pePublicKey) )
768 {
769 scError = SYMCRYPT_AUTHENTICATION_FAILURE;
770 goto cleanup;
771 }
772 }
773 else if ( ( flags & SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION ) == 0 )
774 {
775 // Perform Public key validation on generated public key.
776 // Always perform range validation
777 // May also perform validation that Public key is in subgroup of order Q, depending on flags
779 pkDlkey,
780 fValidatePublicKeyOrder,
781 pbScratch,
782 cbScratch );
783 if ( scError != SYMCRYPT_NO_ERROR )
784 {
785 goto cleanup;
786 }
787 }
788 }
789
790 pkDlkey->fAlgorithmInfo = flags; // We want to track all of the flags in the Dlkey
791
792 if ( (flags & SYMCRYPT_FLAG_KEY_NO_FIPS) == 0 )
793 {
794 if( ( flags & SYMCRYPT_FLAG_DLKEY_DSA ) != 0 )
795 {
796 // Ensure DSA algorithm selftest is run before first use of DSA algorithm
800
801 // PCT does not need to be run on import - mark it as done
802 pkDlkey->fAlgorithmInfo |= SYMCRYPT_PCT_DSA;
803 }
804
805 if( ( flags & SYMCRYPT_FLAG_DLKEY_DH ) != 0 )
806 {
810 }
811 }
812
813cleanup:
814 if (pbScratch!=NULL)
815 {
816 SymCryptWipe( pbScratch, cbScratch );
817 SymCryptCallbackFree( pbScratch );
818 }
819 return scError;
820}
821
822
826 _In_ PCSYMCRYPT_DLKEY pkDlkey,
827 _Out_writes_bytes_( cbPrivateKey )
828 PBYTE pbPrivateKey,
829 SIZE_T cbPrivateKey,
830 _Out_writes_bytes_( cbPublicKey )
831 PBYTE pbPublicKey,
832 SIZE_T cbPublicKey,
833 SYMCRYPT_NUMBER_FORMAT numFormat,
834 UINT32 flags )
835{
836 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
837 PBYTE pbScratch = NULL;
838 UINT32 cbScratch = 0;
839
840 PCSYMCRYPT_DLGROUP pDlgroup = pkDlkey->pDlgroup;
841
843
844 if ( ((pbPrivateKey==NULL) && (cbPrivateKey!=0)) ||
845 ((pbPublicKey==NULL) && (cbPublicKey!=0)) ||
846 ((pbPrivateKey==NULL) && (pbPublicKey==NULL)) ||
847 ((pbPrivateKey!=NULL) && !pkDlkey->fHasPrivateKey) )
848 {
849 scError = SYMCRYPT_INVALID_ARGUMENT;
850 goto cleanup;
851 }
852
853 if (pbPrivateKey != NULL)
854 {
855 scError = SymCryptIntGetValue(
856 pkDlkey->piPrivateKey,
857 pbPrivateKey,
858 cbPrivateKey,
859 numFormat );
860 if (scError!=SYMCRYPT_NO_ERROR)
861 {
862 goto cleanup;
863 }
864 }
865
866 if (pbPublicKey != NULL)
867 {
869 pbScratch = SymCryptCallbackAlloc( cbScratch );
870 if (pbScratch == NULL)
871 {
872 scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
873 goto cleanup;
874 }
875
877 pDlgroup->pmP,
878 pkDlkey->pePublicKey,
879 pbPublicKey,
880 cbPublicKey,
881 numFormat,
882 pbScratch,
883 cbScratch );
884 if (scError!=SYMCRYPT_NO_ERROR)
885 {
886 goto cleanup;
887 }
888 }
889
890cleanup:
891 if (pbScratch!=NULL)
892 {
893 SymCryptWipe( pbScratch, cbScratch );
894 SymCryptCallbackFree( pbScratch );
895 }
896 return scError;
897}
898
902 _Inout_ PSYMCRYPT_DLKEY pkDlkey,
903 UINT32 flags )
904{
905 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
906
907 // Ensure caller has specified what algorithm(s) the key will be used with
909
910 if ( ( ( flags & ~algorithmFlags ) != 0 ) ||
911 ( ( flags & algorithmFlags ) == 0) )
912 {
913 scError = SYMCRYPT_INVALID_ARGUMENT;
914 goto cleanup;
915 }
916
917 pkDlkey->fAlgorithmInfo |= flags;
918
919cleanup:
920 return scError;
921}
unsigned char BOOLEAN
Definition: actypes.h:127
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlkeySetValue(_In_reads_bytes_(cbPrivateKey) PCBYTE pbPrivateKey, SIZE_T cbPrivateKey, _In_reads_bytes_(cbPublicKey) PCBYTE pbPublicKey, SIZE_T cbPublicKey, SYMCRYPT_NUMBER_FORMAT numFormat, UINT32 flags, _Inout_ PSYMCRYPT_DLKEY pkDlkey)
Definition: dlkey.c:541
UINT32 SYMCRYPT_CALL SymCryptDlkeySizeofPublicKey(_In_ PCSYMCRYPT_DLKEY pkDlkey)
Definition: dlkey.c:160
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlkeyPerformPublicKeyValidation(_In_ PCSYMCRYPT_DLKEY pkDlkey, _In_ UINT32 flags, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: dlkey.c:206
UINT32 SYMCRYPT_CALL SymCryptSizeofDlkeyFromDlgroup(_In_ PCSYMCRYPT_DLGROUP pDlgroup)
Definition: dlkey.c:44
UINT32 SYMCRYPT_CALL SymCryptDlkeySizeofPrivateKey(_In_ PCSYMCRYPT_DLKEY pkDlkey)
Definition: dlkey.c:167
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlkeyExtendKeyUsage(_Inout_ PSYMCRYPT_DLKEY pkDlkey, UINT32 flags)
Definition: dlkey.c:901
PCSYMCRYPT_DLGROUP SYMCRYPT_CALL SymCryptDlkeyGetGroup(_In_ PCSYMCRYPT_DLKEY pkDlkey)
Definition: dlkey.c:153
VOID SYMCRYPT_CALL SymCryptDlkeyCopy(_In_ PCSYMCRYPT_DLKEY pkSrc, _Out_ PSYMCRYPT_DLKEY pkDst)
Definition: dlkey.c:109
PSYMCRYPT_DLKEY SYMCRYPT_CALL SymCryptDlkeyAllocate(_In_ PCSYMCRYPT_DLGROUP pDlgroup)
Definition: dlkey.c:12
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlkeySetPrivateKeyLength(_Inout_ PSYMCRYPT_DLKEY pkDlkey, UINT32 nBitsPriv, UINT32 flags)
Definition: dlkey.c:138
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlkeyGenerate(_In_ UINT32 flags, _Inout_ PSYMCRYPT_DLKEY pkDlkey)
Definition: dlkey.c:283
VOID SYMCRYPT_CALL SymCryptDlkeyFree(_Out_ PSYMCRYPT_DLKEY pkObj)
Definition: dlkey.c:35
#define DLKEY_GEN_RANDOM_GENERIC_LIMIT
Definition: dlkey.c:279
VOID SYMCRYPT_CALL SymCryptDlkeyWipe(_Out_ PSYMCRYPT_DLKEY pkDst)
Definition: dlkey.c:102
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDlkeyGetValue(_In_ PCSYMCRYPT_DLKEY pkDlkey, _Out_writes_bytes_(cbPrivateKey) PBYTE pbPrivateKey, SIZE_T cbPrivateKey, _Out_writes_bytes_(cbPublicKey) PBYTE pbPublicKey, SIZE_T cbPublicKey, SYMCRYPT_NUMBER_FORMAT numFormat, UINT32 flags)
Definition: dlkey.c:825
PSYMCRYPT_DLKEY SYMCRYPT_CALL SymCryptDlkeyCreate(_Out_writes_bytes_(cbBuffer) PBYTE pbBuffer, SIZE_T cbBuffer, _In_ PCSYMCRYPT_DLGROUP pDlgroup)
Definition: dlkey.c:52
BOOLEAN SYMCRYPT_CALL SymCryptDlkeyHasPrivateKey(_In_ PCSYMCRYPT_DLKEY pkDlkey)
Definition: dlkey.c:197
#define SYMCRYPT_FLAG_DLKEY_PUBLIC_KEY_ORDER_VALIDATION
Definition: dlkey.c:202
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static void cleanup(void)
Definition: main.c:1335
static MonoProfilerRuntimeShutdownBeginCallback cb
Definition: metahost.c:118
UINT32 SYMCRYPT_CALL SymCryptFdefRawIsEqualUint32(_In_reads_(nDigits *SYMCRYPT_FDEF_DIGIT_NUINT32) PCUINT32 pSrc1, UINT32 nDigits, _In_ UINT32 u32Src2)
Definition: fdef_general.c:730
GLuint res
Definition: glext.h:9613
GLbitfield flags
Definition: glext.h:7161
GLfloat GLfloat p
Definition: glext.h:8902
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
void SYMCRYPT_CALL SymCryptCallbackFree(void *ptr)
Definition: implglue.c:42
void *SYMCRYPT_CALL SymCryptCallbackAlloc(SIZE_T size)
Definition: implglue.c:37
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptCallbackRandom(BYTE *buf, SIZE_T size)
Definition: implglue.c:56
#define _In_reads_bytes_(s)
Definition: no_sal2.h:170
#define _Inout_
Definition: no_sal2.h:162
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _Out_writes_bytes_(s)
Definition: no_sal2.h:178
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
BYTE * PBYTE
Definition: pedump.c:66
#define SYMCRYPT_ASSERT_ASYM_ALIGNED(_p)
Definition: sc_lib.h:1912
#define SYMCRYPT_RUN_KEY_GEN_PCT(KeySelftestFunction, Key, KeySelftestFlag)
Definition: sc_lib.h:3699
#define SYMCRYPT_RUN_SELFTEST_ONCE(AlgorithmSelftestFunction, AlgorithmSelftestFlag)
Definition: sc_lib.h:3686
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDsaPct(PCSYMCRYPT_DLKEY pkDlkey)
UINT32 UINT32 UINT32 UINT32 cbScratch
SIZE_T cbBuffer
Definition: sc_lib_mldsa.h:405
#define SYMCRYPT_ASSERT(_x)
Definition: symcrypt.h:10807
#define SYMCRYPT_FLAG_DLKEY_DSA
Definition: symcrypt.h:7592
VOID SYMCRYPT_CALL SymCryptWipe(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
Definition: libmain.c:137
_Analysis_noreturn_ VOID SYMCRYPT_CALL SymCryptFatal(UINT32 fatalCode)
VOID SYMCRYPT_CALL SymCryptDsaSelftest(void)
enum _SYMCRYPT_NUMBER_FORMAT SYMCRYPT_NUMBER_FORMAT
VOID SYMCRYPT_CALL SymCryptDhSecretAgreementSelftest(void)
#define SYMCRYPT_FLAG_DLKEY_DH
Definition: symcrypt.h:7593
#define SYMCRYPT_FLAG_KEY_NO_FIPS
Definition: symcrypt.h:7579
#define SYMCRYPT_FLAG_DLKEY_GEN_MODP
Definition: symcrypt.h:8065
@ SYMCRYPT_NUMBER_FORMAT_LSB_FIRST
Definition: symcrypt.h:7016
#define SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION
Definition: symcrypt.h:7586
SYMCRYPT_ERROR
Definition: symcrypt.h:227
PCSYMCRYPT_DLGROUP pDlgroup
@ SYMCRYPT_SELFTEST_ALGORITHM_DSA
@ SYMCRYPT_SELFTEST_ALGORITHM_DH
#define SYMCRYPT_CALL
SYMCRYPT_MODELEMENT * PSYMCRYPT_MODELEMENT
#define SYMCRYPT_FDEF_DIGIT_SIZE
#define SYMCRYPT_PCT_DSA
#define SYMCRYPT_FIPS_ASSERT(x)
SYMCRYPT_DLKEY * PSYMCRYPT_DLKEY
UINT32 nBitsOfQ
#define SYMCRYPT_MAX(_a, _b)
UINT32 cbPrimeQ
#define SYMCRYPT_SET_MAGIC(p)
UINT32 cbModElement
const SYMCRYPT_DLKEY * PCSYMCRYPT_DLKEY
const BYTE * PCBYTE
const UINT32 * PCUINT32
SYMCRYPT_MODULUS * PSYMCRYPT_MODULUS
UINT32 nBitsPriv
SYMCRYPT_MAGIC_FIELD SYMCRYPT_DLKEY
#define SYMCRYPT_CHECK_MAGIC(p)
const SYMCRYPT_DLGROUP * PCSYMCRYPT_DLGROUP
UINT32 SYMCRYPT_CALL SymCryptIntIsLessThan(_In_ PCSYMCRYPT_INT piSrc1, _In_ PCSYMCRYPT_INT piSrc2)
Definition: a_dispatch.c:442
UINT32 SYMCRYPT_CALL SymCryptSizeofModElementFromModulus(PCSYMCRYPT_MODULUS pmMod)
Definition: a_dispatch.c:658
VOID SYMCRYPT_CALL SymCryptIntCopy(_In_ PCSYMCRYPT_INT piSrc, _Out_ PSYMCRYPT_INT piDst)
Definition: a_dispatch.c:161
UINT32 SYMCRYPT_CALL SymCryptModElementIsZero(_In_ PCSYMCRYPT_MODULUS pmMod, _In_ PCSYMCRYPT_MODELEMENT peSrc)
Definition: a_dispatch.c:828
UINT32 SYMCRYPT_CALL SymCryptModElementIsEqual(_In_ PCSYMCRYPT_MODULUS pmMod, _In_ PCSYMCRYPT_MODELEMENT peSrc1, _In_ PCSYMCRYPT_MODELEMENT peSrc2)
Definition: a_dispatch.c:818
VOID SYMCRYPT_CALL SymCryptModSetRandom(_In_ PCSYMCRYPT_MODULUS pmMod, _Out_ PSYMCRYPT_MODELEMENT peDst, UINT32 flags, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: a_dispatch.c:993
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptModElementSetValue(_In_reads_bytes_(cbSrc) PCBYTE pbSrc, SIZE_T cbSrc, SYMCRYPT_NUMBER_FORMAT format, PCSYMCRYPT_MODULUS pmMod, _Out_ PSYMCRYPT_MODELEMENT peDst, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: a_dispatch.c:781
#define SYMCRYPT_FLAG_MODRANDOM_ALLOW_ONE
VOID SymCryptModElementCopy(_In_ PCSYMCRYPT_MODULUS pmMod, _In_ PCSYMCRYPT_MODELEMENT peSrc, _Out_ PSYMCRYPT_MODELEMENT peDst)
Definition: a_dispatch.c:683
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptModElementGetValue(PCSYMCRYPT_MODULUS pmMod, _In_ PCSYMCRYPT_MODELEMENT peSrc, _Out_writes_bytes_(cbDst) PBYTE pbDst, SIZE_T cbDst, SYMCRYPT_NUMBER_FORMAT format, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: a_dispatch.c:804
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptIntSetValue(_In_reads_bytes_(cbSrc) PCBYTE pbSrc, SIZE_T cbSrc, SYMCRYPT_NUMBER_FORMAT format, _Out_ PSYMCRYPT_INT piDst)
Definition: a_dispatch.c:248
PSYMCRYPT_MODELEMENT SYMCRYPT_CALL SymCryptModElementCreate(_Out_writes_bytes_(cbBuffer) PBYTE pbBuffer, SIZE_T cbBuffer, _In_ PCSYMCRYPT_MODULUS pmMod)
Definition: a_dispatch.c:665
VOID SYMCRYPT_CALL SymCryptModElementSetValueUint32(UINT32 value, _In_ PCSYMCRYPT_MODULUS pmMod, _Out_ PSYMCRYPT_MODELEMENT peDst, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: a_dispatch.c:908
#define SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS(_nDigits)
VOID SYMCRYPT_CALL SymCryptModElementToInt(_In_ PCSYMCRYPT_MODULUS pmMod, _In_ PCSYMCRYPT_MODELEMENT peSrc, _Out_ PSYMCRYPT_INT piDst, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: a_dispatch.c:762
PSYMCRYPT_INT SYMCRYPT_CALL SymCryptIntFromModulus(_In_ PSYMCRYPT_MODULUS pmSrc)
Definition: a_dispatch.c:720
#define SYMCRYPT_FLAG_MODRANDOM_ALLOW_MINUSONE
UINT32 SYMCRYPT_CALL SymCryptIntIsEqualUint32(_In_ PCSYMCRYPT_INT piSrc1, _In_ UINT32 u32Src2)
Definition: a_dispatch.c:424
UINT32 SYMCRYPT_CALL SymCryptIntBitsizeOfValue(_In_ PCSYMCRYPT_INT piSrc)
Definition: a_dispatch.c:223
UINT32 SYMCRYPT_CALL SymCryptSizeofIntFromDigits(UINT32 nDigits)
Definition: a_dispatch.c:134
VOID SYMCRYPT_CALL SymCryptModExp(_In_ PCSYMCRYPT_MODULUS pmMod, _In_ PCSYMCRYPT_MODELEMENT peBase, _In_ PCSYMCRYPT_INT piExp, UINT32 nBitsExp, UINT32 flags, _Out_ PSYMCRYPT_MODELEMENT peDst, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: a_dispatch.c:961
VOID SYMCRYPT_CALL SymCryptModElementSetValueNegUint32(UINT32 value, _In_ PCSYMCRYPT_MODULUS pmMod, _Out_ PSYMCRYPT_MODELEMENT peDst, _Out_writes_bytes_(cbScratch) PBYTE pbScratch, SIZE_T cbScratch)
Definition: a_dispatch.c:922
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptIntGetValue(_In_ PCSYMCRYPT_INT piSrc, _Out_writes_bytes_(cbDst) PBYTE pbDst, SIZE_T cbDst, SYMCRYPT_NUMBER_FORMAT format)
Definition: a_dispatch.c:259
#define SYMCRYPT_FLAG_DATA_PUBLIC
PSYMCRYPT_INT SYMCRYPT_CALL SymCryptIntCreate(_Out_writes_bytes_(cbBuffer) PBYTE pbBuffer, SIZE_T cbBuffer, UINT32 nDigits)
Definition: a_dispatch.c:141
#define SYMCRYPT_SCRATCH_BYTES_FOR_MODEXP(_nDigits)
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t UINT32
Definition: typedefs.h:59
unsigned char BYTE
Definition: xxhash.c:193