Coverage Report

Created: 2024-11-21 07:03

/src/SymCrypt/lib/eckey.c
Line
Count
Source (jump to first uncovered line)
1
//
2
// eckey.c   Functions for the ECKEY object
3
//
4
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5
//
6
//
7
8
#include "precomp.h"
9
10
PSYMCRYPT_ECKEY
11
SYMCRYPT_CALL
12
SymCryptEckeyAllocate( _In_ PCSYMCRYPT_ECURVE pCurve )
13
946
{
14
946
    PVOID               p;
15
946
    SIZE_T              cb;
16
946
    PSYMCRYPT_ECKEY     res = NULL;
17
18
946
    cb = SymCryptSizeofEckeyFromCurve( pCurve );
19
20
946
    p = SymCryptCallbackAlloc( cb );
21
22
946
    if ( p==NULL )
23
0
    {
24
0
        goto cleanup;
25
0
    }
26
27
946
    res = SymCryptEckeyCreate( p, cb, pCurve );
28
29
946
cleanup:
30
946
    return res;
31
946
}
32
33
VOID
34
SYMCRYPT_CALL
35
SymCryptEckeyFree( _Out_ PSYMCRYPT_ECKEY pkObj )
36
946
{
37
946
    SYMCRYPT_CHECK_MAGIC( pkObj );
38
946
    SymCryptEckeyWipe( pkObj );
39
946
    SymCryptCallbackFree( pkObj );
40
946
}
41
42
UINT32
43
SYMCRYPT_CALL
44
SymCryptSizeofEckeyFromCurve( _In_ PCSYMCRYPT_ECURVE pCurve )
45
2.83k
{
46
    //
47
    // From symcrypt_internal.h we have:
48
    //      - sizeof results are upper bounded by 2^19
49
    //      - SYMCRYPT_SCRATCH_BYTES results are upper bounded by 2^27 (including RSA and ECURVE)
50
    //      - SymCryptSizeofEcpointFromCurve outputs the size of up to 4 modelements + some overhead
51
    // Thus the following calculation does not overflow the result.
52
    //
53
2.83k
    return sizeof(SYMCRYPT_ECKEY) + SymCryptSizeofEcpointFromCurve( pCurve ) + SymCryptSizeofIntFromDigits(SymCryptEcurveDigitsofScalarMultiplier(pCurve));
54
2.83k
}
55
56
PSYMCRYPT_ECKEY
57
SYMCRYPT_CALL
58
SymCryptEckeyCreate(
59
    _Out_writes_bytes_( cbBuffer )  PBYTE               pbBuffer,
60
                                    SIZE_T              cbBuffer,
61
                                    PCSYMCRYPT_ECURVE   pCurve )
62
946
{
63
946
    PSYMCRYPT_ECKEY         pkObj = NULL;
64
946
    UINT32 privateKeyDigits = SymCryptEcurveDigitsofScalarMultiplier(pCurve);
65
66
946
    SIZE_T cbPublicKey = SymCryptSizeofEcpointFromCurve( pCurve );
67
946
    SIZE_T cbPrivateKey = SymCryptSizeofIntFromDigits( privateKeyDigits );
68
69
946
    UNREFERENCED_PARAMETER( cbBuffer );     // only referenced in ASSERTs...
70
71
946
    SYMCRYPT_ASSERT( pCurve != NULL );
72
946
    SYMCRYPT_ASSERT( cbBuffer >= SymCryptSizeofEckeyFromCurve( pCurve ) );
73
74
946
    SYMCRYPT_ASSERT( cbBuffer >= sizeof(SYMCRYPT_ECKEY) +
75
946
                            cbPublicKey +
76
946
                            cbPrivateKey );
77
78
946
    SYMCRYPT_ASSERT_ASYM_ALIGNED( pbBuffer );
79
80
946
    pkObj = (PSYMCRYPT_ECKEY) pbBuffer;
81
82
946
    pkObj->fAlgorithmInfo = 0;
83
946
    pkObj->hasPrivateKey = FALSE;
84
946
    pkObj->pCurve = pCurve;
85
86
946
    pkObj->poPublicKey = SymCryptEcpointCreate(
87
946
                        pbBuffer + sizeof(SYMCRYPT_ECKEY),
88
946
                        cbPublicKey,
89
946
                        pCurve );
90
946
    SYMCRYPT_ASSERT( pkObj->poPublicKey != NULL );
91
92
946
    pkObj->piPrivateKey = SymCryptIntCreate(
93
946
                        pbBuffer + sizeof(SYMCRYPT_ECKEY) + cbPublicKey,
94
946
                        cbPrivateKey,
95
946
                        privateKeyDigits );
96
946
    SYMCRYPT_ASSERT( pkObj->piPrivateKey );
97
98
    // Setting the magic
99
946
    SYMCRYPT_SET_MAGIC( pkObj );
100
101
946
    return pkObj;
102
946
}
103
104
VOID
105
SYMCRYPT_CALL
106
SymCryptEckeyWipe( _Out_ PSYMCRYPT_ECKEY pkDst )
107
946
{
108
    // Wipe the whole structure in one go.
109
946
    SymCryptWipe( pkDst, SymCryptSizeofEckeyFromCurve( pkDst->pCurve ) );
110
946
}
111
112
VOID
113
SymCryptEckeyCopy(
114
    _In_    PCSYMCRYPT_ECKEY  pkSrc,
115
    _Out_   PSYMCRYPT_ECKEY   pkDst )
116
0
{
117
    //
118
    // in-place copy is somewhat common...
119
    //
120
0
    if( pkSrc != pkDst )
121
0
    {
122
        // Copy the fAlgorithmInfo flags
123
0
        pkDst->fAlgorithmInfo = pkSrc->fAlgorithmInfo;
124
125
        // Copy the hasPrivateKey flag
126
0
        pkDst->hasPrivateKey = pkSrc->hasPrivateKey;
127
128
        // Copy the public key
129
0
        SymCryptEcpointCopy( pkSrc->pCurve, pkSrc->poPublicKey, pkDst->poPublicKey );
130
131
        // Copy the private key
132
0
        SymCryptIntCopy( pkSrc->piPrivateKey, pkDst->piPrivateKey );
133
0
    }
134
0
}
135
136
UINT32
137
SYMCRYPT_CALL
138
SymCryptEckeySizeofPublicKey(
139
    _In_ PCSYMCRYPT_ECKEY           pkEckey,
140
    _In_ SYMCRYPT_ECPOINT_FORMAT    ecPointFormat )
141
1.83k
{
142
    //
143
    // From symcrypt_internal.h we have:
144
    //      - sizeof results are upper bounded by 2^19
145
    //      - SYMCRYPT_SCRATCH_BYTES results are upper bounded by 2^27 (including RSA and ECURVE)
146
    //      - SymCryptEcpointFormatNumberofElements returns up to 4 elements.
147
    //
148
    // Thus the following calculation does not overflow cbScratch.
149
    //
150
1.83k
    return SymCryptEcpointFormatNumberofElements[ecPointFormat] * SymCryptEcurveSizeofFieldElement( pkEckey->pCurve );
151
1.83k
}
152
153
UINT32
154
SYMCRYPT_CALL
155
SymCryptEckeySizeofPrivateKey( _In_ PCSYMCRYPT_ECKEY pkEckey )
156
653
{
157
653
    return SymCryptEcurveSizeofScalarMultiplier( pkEckey->pCurve );
158
653
}
159
160
BOOLEAN
161
SYMCRYPT_CALL
162
SymCryptEckeyHasPrivateKey( _In_ PCSYMCRYPT_ECKEY pkEckey )
163
0
{
164
0
    return pkEckey->hasPrivateKey;
165
0
}
166
167
1.63k
#define SYMCRYPT_FLAG_ECKEY_PUBLIC_KEY_ORDER_VALIDATION (0x1)
168
169
SYMCRYPT_ERROR
170
SYMCRYPT_CALL
171
SymCryptEckeyPerformPublicKeyValidation(
172
    _In_                            PCSYMCRYPT_ECKEY        pEckey,
173
    _In_                            UINT32                  flags,
174
    _Out_writes_bytes_( cbScratch ) PBYTE                   pbScratch,
175
                                    SIZE_T                  cbScratch )
176
816
{
177
816
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
178
179
816
    PCSYMCRYPT_ECURVE   pCurve = pEckey->pCurve;
180
181
816
    PSYMCRYPT_ECPOINT   poNPub = NULL;
182
816
    UINT32              cbNPub = SymCryptSizeofEcpointFromCurve( pCurve );
183
184
    // This is an excessive amount of space to require, but all callers can currently provide it, and it's easy to phrase
185
816
    SYMCRYPT_ASSERT( cbScratch >= SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_ECKEY_ECURVE_OPERATIONS( pCurve ) );
186
187
816
    SYMCRYPT_ASSERT( cbScratch >= cbNPub );
188
189
    // Check if Public key is O
190
816
    if ( SymCryptEcpointIsZero( pCurve, pEckey->poPublicKey, pbScratch, cbScratch ) )
191
0
    {
192
0
        return SYMCRYPT_INVALID_ARGUMENT;
193
0
    }
194
195
    // Public key is represented by Modelements of the underlying finite field for the curve
196
    // If we have reached this point we have either:
197
    // Constructed the Public key to have coordinates in the field (Generate case), or
198
    // Verified the Public key has coordinates in the field (SetValue case)
199
200
    // Check that Public key is on the curve
201
    // Skip check for Montgomery curves as we do not have an EcpointOnCurve function for them
202
816
    if ( !SYMCRYPT_CURVE_IS_MONTGOMERY_TYPE(pCurve) &&
203
816
        !SymCryptEcpointOnCurve( pCurve, pEckey->poPublicKey, pbScratch, cbScratch ) )
204
23
    {
205
23
        return SYMCRYPT_INVALID_ARGUMENT;
206
23
    }
207
208
    // Perform validation that Public key is in a subgroup of order GOrd.
209
793
    if ( (flags & SYMCRYPT_FLAG_ECKEY_PUBLIC_KEY_ORDER_VALIDATION) != 0 )
210
788
    {
211
788
        if ( SymCryptIntIsEqualUint32( pCurve->H, 1 ) )
212
719
        {
213
            // If cofactor is 1 then to validate that Public key has order GOrd
214
            // it is sufficient to validate Public key is on the curve
215
            // We just performed this check - so we are done.
216
719
        }
217
69
        else
218
69
        {
219
            // Ensure GOrd*(Public key) == O
220
69
            poNPub = SymCryptEcpointCreate( pbScratch, cbNPub, pCurve );
221
69
            pbScratch += cbNPub;
222
69
            cbScratch -= cbNPub;
223
224
69
            SYMCRYPT_ASSERT( poNPub != NULL );
225
226
            // Do the multiplication
227
69
            scError = SymCryptEcpointScalarMul(
228
69
                pCurve,
229
69
                SymCryptIntFromModulus( pCurve->GOrd ),
230
69
                pEckey->poPublicKey,
231
69
                0, // Do not multiply by cofactor!
232
69
                poNPub,
233
69
                pbScratch,
234
69
                cbScratch );
235
69
            if ( scError != SYMCRYPT_NO_ERROR )
236
0
            {
237
0
                return scError;
238
0
            }
239
240
69
            if ( !SymCryptEcpointIsZero( pCurve, poNPub, pbScratch, cbScratch ) )
241
0
            {
242
0
                return SYMCRYPT_INVALID_ARGUMENT;
243
0
            }
244
69
        }
245
788
    }
246
247
793
    return SYMCRYPT_NO_ERROR;
248
793
}
249
250
SYMCRYPT_ERROR
251
SYMCRYPT_CALL
252
SymCryptEckeySetValue(
253
    _In_reads_bytes_( cbPrivateKey )
254
            PCBYTE                  pbPrivateKey,
255
            SIZE_T                  cbPrivateKey,
256
    _In_reads_bytes_( cbPublicKey )
257
            PCBYTE                  pbPublicKey,
258
            SIZE_T                  cbPublicKey,
259
            SYMCRYPT_NUMBER_FORMAT  numFormat,
260
            SYMCRYPT_ECPOINT_FORMAT ecPointFormat,
261
            UINT32                  flags,
262
    _Inout_ PSYMCRYPT_ECKEY         pEckey )
263
842
{
264
842
    SYMCRYPT_ERROR      scError = SYMCRYPT_NO_ERROR;
265
842
    PBYTE               pbScratch = NULL;
266
842
    UINT32              cbScratch = 0;
267
842
    PBYTE               pbScratchInternal = NULL;
268
842
    UINT32              cbScratchInternal = 0;
269
270
842
    PCSYMCRYPT_ECURVE   pCurve = pEckey->pCurve;
271
272
842
    PSYMCRYPT_ECPOINT   poTmp = NULL;
273
842
    UINT32              cbTmp = 0;
274
275
842
    PSYMCRYPT_INT           piTmpInteger = NULL;
276
842
    UINT32                  cbTmpInteger = 0;
277
842
    PSYMCRYPT_MODELEMENT    peTmpModElement = NULL;
278
842
    UINT32                  cbTmpModElement = pCurve->cbModElement;
279
280
842
    UINT32 privateKeyDigits = SymCryptEcurveDigitsofScalarMultiplier(pCurve);
281
282
842
    UINT32 fValidatePublicKeyOrder = SYMCRYPT_FLAG_ECKEY_PUBLIC_KEY_ORDER_VALIDATION;
283
284
    // Ensure caller has specified what algorithm(s) the key will be used with
285
842
    UINT32 algorithmFlags = SYMCRYPT_FLAG_ECKEY_ECDSA | SYMCRYPT_FLAG_ECKEY_ECDH;
286
    // Make sure only allowed flags are specified
287
842
    UINT32 allowedFlags = SYMCRYPT_FLAG_KEY_NO_FIPS | SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION | algorithmFlags;
288
289
842
    if ( ( ( flags & ~allowedFlags ) != 0 ) ||
290
842
         ( ( flags & algorithmFlags ) == 0 ) )
291
0
    {
292
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
293
0
        goto cleanup;
294
0
    }
295
296
    // Check that minimal validation flag only specified with no fips
297
842
    if ( ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 ) &&
298
842
         ( ( flags & SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION ) != 0 ) )
299
0
    {
300
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
301
0
        goto cleanup;
302
0
    }
303
304
842
    if ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) != 0 )
305
5
    {
306
5
        fValidatePublicKeyOrder = 0;
307
5
    }
308
309
842
    if ( ( ( cbPrivateKey == 0 ) && ( cbPublicKey == 0 ) ) ||
310
842
         ( ( cbPrivateKey != 0 ) && ( cbPrivateKey != SymCryptEcurveSizeofScalarMultiplier( pEckey->pCurve ) ) ) ||
311
842
         ( ( cbPublicKey != 0 )  && ( cbPublicKey != SymCryptEckeySizeofPublicKey( pEckey, ecPointFormat ) ) ) )
312
0
    {
313
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
314
0
        goto cleanup;
315
0
    }
316
317
    // Allocate scratch space
318
842
    cbScratch = SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_ECKEY_ECURVE_OPERATIONS( pCurve );
319
842
    pbScratch = SymCryptCallbackAlloc( cbScratch );
320
842
    if ( pbScratch == NULL )
321
0
    {
322
0
        scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
323
0
        goto cleanup;
324
0
    }
325
326
842
    if ( pbPrivateKey != NULL )
327
623
    {
328
        //
329
        // Private key calculations
330
        //
331
332
623
        pbScratchInternal = pbScratch;
333
623
        cbScratchInternal = cbScratch;
334
335
        // Allocate the integer
336
623
        cbTmpInteger = SymCryptSizeofIntFromDigits( privateKeyDigits );
337
623
        piTmpInteger = SymCryptIntCreate( pbScratchInternal, cbTmpInteger, privateKeyDigits );
338
623
        SYMCRYPT_ASSERT( piTmpInteger != NULL );
339
340
623
        pbScratchInternal += cbTmpInteger;
341
623
        cbScratchInternal -= cbTmpInteger;
342
343
        // Allocate the modelement
344
623
        peTmpModElement = SymCryptModElementCreate( pbScratchInternal, cbTmpModElement, pCurve->GOrd );
345
623
        SYMCRYPT_ASSERT( peTmpModElement != NULL );
346
347
623
        pbScratchInternal += cbTmpModElement;
348
623
        cbScratchInternal -= cbTmpModElement;
349
350
        // Get the "raw" private key
351
623
        scError = SymCryptIntSetValue( pbPrivateKey, cbPrivateKey, numFormat, piTmpInteger );
352
623
        if (scError != SYMCRYPT_NO_ERROR)
353
0
        {
354
0
            goto cleanup;
355
0
        }
356
357
        // Validation steps
358
623
        if ( ( flags & SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION ) == 0 )
359
623
        {
360
            // Perform range validation on imported Private key if it is in canonical format
361
623
            if ( pCurve->PrivateKeyDefaultFormat == SYMCRYPT_ECKEY_PRIVATE_FORMAT_CANONICAL )
362
573
            {
363
                // Check if Private key is greater than or equal to GOrd
364
573
                if ( !SymCryptIntIsLessThan( piTmpInteger, SymCryptIntFromModulus( pCurve->GOrd ) ) )
365
20
                {
366
20
                    scError = SYMCRYPT_INVALID_ARGUMENT;
367
20
                    goto cleanup;
368
20
                }
369
573
            }
370
371
            // "TimesH" formats
372
            // IntGetBits requirements:
373
            //      We know that coFactorPower is up to SYMCRYPT_ECURVE_MAX_COFACTOR_POWER. Thus
374
            //      less than 32 and less than the digits size in bits.
375
603
            if ( (pCurve->coFactorPower>0) &&
376
603
                (pCurve->PrivateKeyDefaultFormat == SYMCRYPT_ECKEY_PRIVATE_FORMAT_DIVH_TIMESH) &&
377
603
                (SymCryptIntGetBits( piTmpInteger, 0, pCurve->coFactorPower) != 0) )
378
0
            {
379
0
                scError = SYMCRYPT_INVALID_ARGUMENT;
380
0
                goto cleanup;
381
0
            }
382
383
384
            // High bit restrictions
385
            // IntGetBits requirements:
386
            //      Satisfied by asserting that
387
            //      HighBitRestrictionPosition + HighBitRestrictionNumOfBits <= GOrdBitsize + coFactorPower
388
            //      during EcurveAllocate.
389
603
            if ( (pCurve->HighBitRestrictionNumOfBits>0) &&
390
603
                (SymCryptIntGetBits(
391
0
                    piTmpInteger,
392
0
                    pCurve->HighBitRestrictionPosition,
393
0
                    pCurve->HighBitRestrictionNumOfBits) != pCurve->HighBitRestrictionValue) )
394
0
            {
395
0
                scError = SYMCRYPT_INVALID_ARGUMENT;
396
0
                goto cleanup;
397
0
            }
398
603
        }
399
400
        // Convert the private key to "DivH" format
401
603
        if (pCurve->coFactorPower>0)
402
50
        {
403
            // "TimesH" format: Divide the input private key with the cofactor
404
            // by shifting right the appropriate number of bits
405
50
            if (pCurve->PrivateKeyDefaultFormat == SYMCRYPT_ECKEY_PRIVATE_FORMAT_DIVH_TIMESH)
406
0
            {
407
0
                SymCryptIntDivPow2( piTmpInteger, pCurve->coFactorPower, piTmpInteger );
408
0
            }
409
410
            // "Canonical" format: Divide by h modulo GOrd
411
50
            if (pCurve->PrivateKeyDefaultFormat == SYMCRYPT_ECKEY_PRIVATE_FORMAT_CANONICAL)
412
0
            {
413
0
                SymCryptIntToModElement( piTmpInteger, pCurve->GOrd, peTmpModElement, pbScratchInternal, cbScratchInternal );
414
0
                SymCryptModDivPow2( pCurve->GOrd, peTmpModElement, pCurve->coFactorPower, peTmpModElement, pbScratchInternal, cbScratchInternal );
415
0
                SymCryptModElementToInt( pCurve->GOrd, peTmpModElement, piTmpInteger, pbScratchInternal, cbScratchInternal );
416
0
            }
417
50
        }
418
419
        // Divide the input private key since it could be larger than subgroup order
420
603
        SymCryptIntDivMod(
421
603
            piTmpInteger,
422
603
            SymCryptDivisorFromModulus(pCurve->GOrd),
423
603
            NULL,
424
603
            piTmpInteger,
425
603
            pbScratchInternal,
426
603
            cbScratchInternal );
427
428
        // Check if Private key is 0 after dividing it by the subgroup order
429
        // Other part of range validation - perform unconditionally as it is cheap
430
        // and it never makes sense for private key to be 0 intentionally
431
603
        if (SymCryptIntIsEqualUint32( piTmpInteger, 0 ))
432
6
        {
433
6
            scError = SYMCRYPT_INVALID_ARGUMENT;
434
6
            goto cleanup;
435
6
        }
436
437
        // Copy into the ECKEY
438
597
        SymCryptIntCopy( piTmpInteger, pEckey->piPrivateKey );
439
440
597
        pEckey->hasPrivateKey = TRUE;
441
597
    }
442
443
816
    if ( pbPublicKey != NULL )
444
224
    {
445
224
        scError = SymCryptEcpointSetValue(
446
224
                            pCurve,
447
224
                            pbPublicKey,
448
224
                            cbPublicKey,
449
224
                            numFormat,
450
224
                            ecPointFormat,
451
224
                            pEckey->poPublicKey,
452
224
                            SYMCRYPT_FLAG_DATA_PUBLIC,
453
224
                            pbScratch,
454
224
                            cbScratch );
455
224
        if ( scError != SYMCRYPT_NO_ERROR )
456
0
        {
457
0
            goto cleanup;
458
0
        }
459
460
        // Perform Public key validation on imported Public key.
461
224
        if ( ( flags & SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION ) == 0 )
462
224
        {
463
224
            scError = SymCryptEckeyPerformPublicKeyValidation(
464
224
                pEckey,
465
224
                fValidatePublicKeyOrder,
466
224
                pbScratch,
467
224
                cbScratch );
468
224
            if ( scError != SYMCRYPT_NO_ERROR )
469
23
            {
470
23
                goto cleanup;
471
23
            }
472
224
        }
473
224
    }
474
475
    // Calculating the public key if no key was provided
476
    // or if needed for keypair regeneration validation
477
793
    if ( (pbPublicKey==NULL) ||
478
793
         ( ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 ) &&
479
201
          (pbPrivateKey!=NULL) && (pbPublicKey!=NULL) ) )
480
592
    {
481
        // Calculate the public key from the private key
482
592
        pbScratchInternal = pbScratch;
483
592
        cbScratchInternal = cbScratch;
484
485
        // By default calculate the Public key directly where it will be persisted
486
592
        poTmp = pEckey->poPublicKey;
487
488
592
        if ( pbPublicKey != NULL )
489
0
        {
490
            // If doing regeneration validation calculate the Public key in scratch
491
0
            cbTmp = SymCryptSizeofEcpointFromCurve( pCurve );
492
0
            poTmp = SymCryptEcpointCreate( pbScratchInternal, cbTmp, pCurve );
493
0
            pbScratchInternal += cbTmp;
494
0
            cbScratchInternal -= cbTmp;
495
0
        }
496
497
592
        SYMCRYPT_ASSERT( poTmp != NULL );
498
499
        // Always multiply by the cofactor since the internal format is "DIVH"
500
592
        scError = SymCryptEcpointScalarMul(
501
592
            pCurve,
502
592
            pEckey->piPrivateKey,
503
592
            NULL,
504
592
            SYMCRYPT_FLAG_ECC_LL_COFACTOR_MUL,
505
592
            poTmp,
506
592
            pbScratchInternal,
507
592
            cbScratchInternal );
508
592
        if ( scError != SYMCRYPT_NO_ERROR )
509
0
        {
510
0
            goto cleanup;
511
0
        }
512
513
592
        if ( pbPublicKey != NULL )
514
0
        {
515
0
            if ( !SymCryptEcpointIsEqual( pCurve, poTmp, pEckey->poPublicKey, 0, pbScratchInternal, cbScratchInternal ) )
516
0
            {
517
0
                scError = SYMCRYPT_INVALID_ARGUMENT;
518
0
                goto cleanup;
519
0
            }
520
0
        }
521
592
        else if ( ( flags & SYMCRYPT_FLAG_KEY_MINIMAL_VALIDATION ) == 0 )
522
592
        {
523
            // Perform Public key validation on generated Public key.
524
592
            scError = SymCryptEckeyPerformPublicKeyValidation(
525
592
                pEckey,
526
592
                fValidatePublicKeyOrder,
527
592
                pbScratch,
528
592
                cbScratch );
529
592
            if ( scError != SYMCRYPT_NO_ERROR )
530
0
            {
531
0
                goto cleanup;
532
0
            }
533
592
        }
534
592
    }
535
536
793
    pEckey->fAlgorithmInfo = flags; // We want to track all of the flags in the Eckey
537
538
793
    if ( ( flags & SYMCRYPT_FLAG_KEY_NO_FIPS ) == 0 )
539
788
    {
540
788
        if ( ( flags & SYMCRYPT_FLAG_ECKEY_ECDSA ) != 0 )
541
788
        {
542
            // Ensure ECDSA algorithm selftest is run before first use of ECDSA algorithm
543
788
            SYMCRYPT_RUN_SELFTEST_ONCE(
544
788
                SymCryptEcDsaSelftest,
545
788
                SYMCRYPT_SELFTEST_ALGORITHM_ECDSA );
546
547
            // ECDSA PCT is deferred until the key is used or exported - see SymCryptEcDsaSign and
548
            // SymCryptEckeyGetValue
549
788
        }
550
551
788
        if ( ( flags & SYMCRYPT_FLAG_ECKEY_ECDH ) != 0 )
552
0
        {
553
0
            SYMCRYPT_RUN_SELFTEST_ONCE(
554
0
                SymCryptEcDhSecretAgreementSelftest,
555
0
                SYMCRYPT_SELFTEST_ALGORITHM_ECDH );
556
0
        }
557
788
    }
558
559
842
cleanup:
560
561
842
    if ( pbScratch != NULL )
562
842
    {
563
842
        SymCryptWipe( pbScratch, cbScratch );
564
842
        SymCryptCallbackFree( pbScratch );
565
842
    }
566
567
842
    return scError;
568
793
}
569
570
SYMCRYPT_ERROR
571
SYMCRYPT_CALL
572
SymCryptEckeyGetValue(
573
    _In_    PCSYMCRYPT_ECKEY        pEckey,
574
    _Out_writes_bytes_( cbPrivateKey )
575
            PBYTE                   pbPrivateKey,
576
            SIZE_T                  cbPrivateKey,
577
    _Out_writes_bytes_( cbPublicKey )
578
            PBYTE                   pbPublicKey,
579
            SIZE_T                  cbPublicKey,
580
            SYMCRYPT_NUMBER_FORMAT  numFormat,
581
            SYMCRYPT_ECPOINT_FORMAT ecPointFormat,
582
            UINT32                  flags )
583
587
{
584
587
    SYMCRYPT_ERROR      scError = SYMCRYPT_NO_ERROR;
585
587
    PBYTE               pbScratch = NULL;
586
587
    UINT32              cbScratch = 0;
587
587
    PBYTE               pbScratchInternal = NULL;
588
587
    UINT32              cbScratchInternal = 0;
589
590
587
    PCSYMCRYPT_ECURVE   pCurve = pEckey->pCurve;
591
592
587
    PSYMCRYPT_INT           piTmpInteger = NULL;
593
587
    UINT32                  cbTmpInteger = 0;
594
587
    PSYMCRYPT_MODELEMENT    peTmpModElement = NULL;
595
587
    UINT32                  cbTmpModElement = pCurve->cbModElement;
596
597
587
    UINT32 privateKeyDigits = SymCryptEcurveDigitsofScalarMultiplier(pCurve);
598
599
587
    SYMCRYPT_ASSERT( (cbPrivateKey==0) || (cbPrivateKey == SymCryptEcurveSizeofScalarMultiplier( pEckey->pCurve )) );
600
587
    SYMCRYPT_ASSERT( (cbPublicKey==0) || (cbPublicKey == SymCryptEckeySizeofPublicKey( pEckey, ecPointFormat)) );
601
602
    // Make sure we only specify the correct flags
603
587
    if (flags != 0)
604
0
    {
605
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
606
0
        goto cleanup;
607
0
    }
608
609
    // Allocate scratch space
610
587
    cbScratch = SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_ECKEY_ECURVE_OPERATIONS( pCurve );
611
587
    pbScratch = SymCryptCallbackAlloc( cbScratch );
612
587
    if ( pbScratch == NULL )
613
0
    {
614
0
        scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
615
0
        goto cleanup;
616
0
    }
617
618
587
    pbScratchInternal = pbScratch;
619
587
    cbScratchInternal = cbScratch;
620
621
    // Allocate the integer
622
587
    cbTmpInteger = SymCryptSizeofIntFromDigits( privateKeyDigits );
623
587
    piTmpInteger = SymCryptIntCreate( pbScratchInternal, cbTmpInteger, privateKeyDigits );
624
587
    SYMCRYPT_ASSERT( piTmpInteger != NULL );
625
626
587
    pbScratchInternal += cbTmpInteger;
627
587
    cbScratchInternal -= cbTmpInteger;
628
629
    // Allocate the modelement
630
587
    peTmpModElement = SymCryptModElementCreate( pbScratchInternal, cbTmpModElement, pCurve->GOrd );
631
587
    SYMCRYPT_ASSERT( peTmpModElement != NULL );
632
633
587
    pbScratchInternal += cbTmpModElement;
634
587
    cbScratchInternal -= cbTmpModElement;
635
636
587
    if ((cbPrivateKey == 0) && (cbPublicKey == 0))
637
0
    {
638
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
639
0
        goto cleanup;
640
0
    }
641
642
587
    if (cbPrivateKey != 0)
643
0
    {
644
0
        if (!pEckey->hasPrivateKey)
645
0
        {
646
0
            scError = SYMCRYPT_INVALID_BLOB;
647
0
            goto cleanup;
648
0
        }
649
650
        // If this keypair may be used in ECDSA, and does not have the no FIPS flag, run the PCT if
651
        // it has not already been run
652
0
        if ( ((pEckey->fAlgorithmInfo & SYMCRYPT_FLAG_ECKEY_ECDSA) != 0) &&
653
0
             ((pEckey->fAlgorithmInfo & SYMCRYPT_FLAG_KEY_NO_FIPS) == 0) )
654
0
        {
655
0
            SYMCRYPT_RUN_KEY_PCT(
656
0
                SymCryptEcDsaPct,
657
0
                pEckey,
658
0
                SYMCRYPT_PCT_ECDSA );
659
0
        }
660
661
        // Copy the key into the temporary integer
662
0
        SymCryptIntCopy( pEckey->piPrivateKey, piTmpInteger );
663
664
        // Convert the "DivH" format into the external format
665
0
        if (pCurve->coFactorPower>0)
666
0
        {
667
            // For the "Canonical" format: Multiply the integer by h
668
            // and then take the result modulo GOrd
669
0
            if (pCurve->PrivateKeyDefaultFormat == SYMCRYPT_ECKEY_PRIVATE_FORMAT_CANONICAL)
670
0
            {
671
0
                SymCryptIntMulPow2( piTmpInteger, pCurve->coFactorPower, piTmpInteger );
672
0
                SymCryptIntDivMod(
673
0
                    piTmpInteger,
674
0
                    SymCryptDivisorFromModulus(pCurve->GOrd),
675
0
                    NULL,
676
0
                    piTmpInteger,
677
0
                    pbScratchInternal,
678
0
                    cbScratchInternal );
679
0
            }
680
681
            // For the "TimesH" format: Multiply the integer by h again by shifting
682
0
            if (pCurve->PrivateKeyDefaultFormat == SYMCRYPT_ECKEY_PRIVATE_FORMAT_DIVH_TIMESH)
683
0
            {
684
0
                SymCryptIntMulPow2( piTmpInteger, pCurve->coFactorPower, piTmpInteger );
685
0
            }
686
0
        }
687
688
0
        scError = SymCryptIntGetValue( piTmpInteger, pbPrivateKey, cbPrivateKey, numFormat );
689
0
        if (scError != SYMCRYPT_NO_ERROR)
690
0
        {
691
0
            goto cleanup;
692
0
        }
693
0
    }
694
695
587
    if (cbPublicKey != 0)
696
587
    {
697
587
        scError = SymCryptEcpointGetValue(
698
587
                            pCurve,
699
587
                            pEckey->poPublicKey,
700
587
                            numFormat,
701
587
                            ecPointFormat,
702
587
                            pbPublicKey,
703
587
                            cbPublicKey,
704
587
                            SYMCRYPT_FLAG_DATA_PUBLIC,
705
587
                            pbScratch,
706
587
                            cbScratch );
707
587
    }
708
709
587
cleanup:
710
711
587
    if ( pbScratch != NULL )
712
587
    {
713
587
        SymCryptWipe( pbScratch, cbScratch );
714
587
        SymCryptCallbackFree( pbScratch );
715
587
    }
716
717
587
    return scError;
718
587
}
719
720
0
#define SYMCRYPT_ECPOINT_SET_RANDOM_MAX_TRIES   (1000)
721
722
SYMCRYPT_ERROR
723
SYMCRYPT_CALL
724
SymCryptEckeySetRandom(
725
    _In_    UINT32                  flags,
726
    _Inout_ PSYMCRYPT_ECKEY         pEckey )
727
0
{
728
0
    SYMCRYPT_ERROR      scError = SYMCRYPT_NO_ERROR;
729
0
    PBYTE               pbScratch = NULL;
730
0
    UINT32              cbScratch = 0;
731
0
    PBYTE               pbScratchInternal = NULL;
732
0
    UINT32              cbScratchInternal = 0;
733
734
0
    PCSYMCRYPT_ECURVE   pCurve = pEckey->pCurve;
735
    
736
0
    PSYMCRYPT_ECPOINT   poTmp = NULL;
737
0
    UINT32              cbTmp = 0;
738
739
0
    INT32 cntr = SYMCRYPT_ECPOINT_SET_RANDOM_MAX_TRIES;
740
741
0
    PSYMCRYPT_MODELEMENT peScalar = NULL;
742
0
    PSYMCRYPT_INT        piScalar = NULL;
743
0
    UINT32               cbScalar = 0;
744
745
0
    UINT32 highBitRestrictionPosition = pCurve->HighBitRestrictionPosition;
746
747
    // Ensure caller has specified what algorithm(s) the key will be used with
748
0
    UINT32 algorithmFlags = SYMCRYPT_FLAG_ECKEY_ECDSA | SYMCRYPT_FLAG_ECKEY_ECDH;
749
    // Make sure only allowed flags are specified
750
0
    UINT32 allowedFlags = SYMCRYPT_FLAG_KEY_NO_FIPS | algorithmFlags;
751
752
0
    if ( ( ( flags & ~allowedFlags ) != 0 ) ||
753
0
         ( ( flags & algorithmFlags ) == 0 ) )
754
0
    {
755
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
756
0
        goto cleanup;
757
0
    }
758
759
    //
760
    // From symcrypt_internal.h we have:
761
    //      - sizeof results are upper bounded by 2^19
762
    //      - SYMCRYPT_SCRATCH_BYTES results are upper bounded by 2^27 (including RSA and ECURVE)
763
    // Thus the following calculation does not overflow cbScratch.
764
    //
765
0
    cbScratch = SYMCRYPT_INTERNAL_SCRATCH_BYTES_FOR_ECKEY_ECURVE_OPERATIONS( pCurve );
766
0
    pbScratch = SymCryptCallbackAlloc( cbScratch );
767
0
    if ( pbScratch == NULL )
768
0
    {
769
0
        scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
770
0
        goto cleanup;
771
0
    }
772
773
    // Allocating temporaries
774
0
    pbScratchInternal = pbScratch;
775
0
    cbScratchInternal = cbScratch;
776
777
0
    peScalar = SymCryptModElementCreate( pbScratchInternal, pCurve->cbModElement, pCurve->GOrd );
778
0
    SYMCRYPT_ASSERT( peScalar != NULL );
779
780
0
    pbScratchInternal += pCurve->cbModElement;
781
0
    cbScratchInternal -= pCurve->cbModElement;
782
783
0
    cbScalar = SymCryptSizeofIntFromDigits( SymCryptEcurveDigitsofScalarMultiplier(pCurve) );
784
0
    piScalar = SymCryptIntCreate( pbScratchInternal, cbScalar, SymCryptEcurveDigitsofScalarMultiplier(pCurve) );
785
786
0
    pbScratchInternal += cbScalar;
787
0
    cbScratchInternal -= cbScalar;
788
789
    // Shift the high bit position if the format is "TIMESH"
790
    //  Note:   Do not actually multiply the integer as we will check if it is
791
    //          less than the group order
792
0
    if (pCurve->PrivateKeyDefaultFormat == SYMCRYPT_ECKEY_PRIVATE_FORMAT_DIVH_TIMESH)
793
0
    {
794
0
        highBitRestrictionPosition -= pCurve->coFactorPower;
795
0
    }
796
797
    // Main loop
798
0
    do
799
0
    {
800
        // We perform Private key range validation by construction
801
        // Setting a random mod element in the [1, SubgroupOrder-1] set
802
        // This will be the "DivH" format of the private key. This means
803
        // that PublicKey = h * PrivateKey * G
804
0
        SymCryptModSetRandom(
805
0
            pCurve->GOrd,
806
0
            peScalar,
807
0
            (SYMCRYPT_FLAG_MODRANDOM_ALLOW_ONE|SYMCRYPT_FLAG_MODRANDOM_ALLOW_MINUSONE),
808
0
            pbScratchInternal,
809
0
            cbScratchInternal );
810
811
        // Converting to "canonical" format
812
0
        if (pCurve->PrivateKeyDefaultFormat == SYMCRYPT_ECKEY_PRIVATE_FORMAT_CANONICAL)
813
0
        {
814
0
            for (UINT32 i=0; i<pCurve->coFactorPower; i++)
815
0
            {
816
0
                SymCryptModAdd( pCurve->GOrd, peScalar, peScalar, peScalar, pbScratchInternal, cbScratchInternal );
817
0
            }
818
0
        }
819
820
        // Set the temporary scalar to verify the format
821
0
        SymCryptModElementToInt( pCurve->GOrd, peScalar, piScalar, pbScratchInternal, cbScratchInternal );
822
823
0
        if (pCurve->HighBitRestrictionNumOfBits > 0)
824
0
        {
825
            // Set the desired bits
826
0
            SymCryptIntSetBits(
827
0
                    piScalar,
828
0
                    pCurve->HighBitRestrictionValue,
829
0
                    highBitRestrictionPosition,
830
0
                    pCurve->HighBitRestrictionNumOfBits );
831
832
            // Make sure we didn't exceed the group order
833
0
            if ( SymCryptIntIsLessThan(
834
0
                    piScalar,
835
0
                    SymCryptIntFromModulus( pCurve->GOrd )) )
836
0
            {
837
0
                break;
838
0
            }
839
0
        }
840
0
        else
841
0
        {
842
            // No high bit restriction was specified
843
0
            break;
844
0
        }
845
846
0
        cntr--;
847
0
    }
848
0
    while (cntr>0);
849
850
0
    if (cntr <= 0)
851
0
    {
852
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
853
0
        goto cleanup;
854
0
    }
855
856
    // Here piScalar has a private key that satisfies the restriction(s)
857
    // Move it to the modelement
858
0
    SymCryptIntToModElement( piScalar, pCurve->GOrd, peScalar, pbScratchInternal, cbScratchInternal );
859
860
    // Convert the private key back to "DIVH" format
861
0
    if (pCurve->PrivateKeyDefaultFormat == SYMCRYPT_ECKEY_PRIVATE_FORMAT_CANONICAL)
862
0
    {
863
0
        SymCryptModDivPow2( pCurve->GOrd, peScalar, pCurve->coFactorPower, peScalar, pbScratchInternal, cbScratchInternal );
864
0
    }
865
866
    // Set the private key
867
0
    SymCryptModElementToInt( pCurve->GOrd, peScalar, pEckey->piPrivateKey, pbScratchInternal, cbScratchInternal );
868
869
    // Do the multiplication (pass over the entire scratch space as it is not needed anymore)
870
0
    scError = SymCryptEcpointScalarMul(
871
0
        pCurve,
872
0
        pEckey->piPrivateKey,
873
0
        NULL,
874
0
        SYMCRYPT_FLAG_ECC_LL_COFACTOR_MUL,
875
0
        pEckey->poPublicKey,
876
0
        pbScratch,
877
0
        cbScratch );
878
0
    if ( scError != SYMCRYPT_NO_ERROR )
879
0
    {
880
0
        goto cleanup;
881
0
    }
882
883
    // Perform range and public key order validation on generated Public key.
884
0
    if ( (flags & SYMCRYPT_FLAG_KEY_NO_FIPS) == 0 )
885
0
    {
886
        // Perform Public key validation.
887
        // Always perform range validation and validation that Public key is in subgroup of order GOrd
888
0
        scError = SymCryptEckeyPerformPublicKeyValidation(
889
0
            pEckey,
890
0
            SYMCRYPT_FLAG_ECKEY_PUBLIC_KEY_ORDER_VALIDATION,
891
0
            pbScratch,
892
0
            cbScratch );
893
0
        if ( scError != SYMCRYPT_NO_ERROR )
894
0
        {
895
0
            goto cleanup;
896
0
        }
897
0
    }
898
899
0
    pEckey->hasPrivateKey = TRUE;
900
901
0
    pEckey->fAlgorithmInfo = flags; // We want to track all of the flags in the Eckey
902
903
0
    if ( (flags & SYMCRYPT_FLAG_KEY_NO_FIPS) == 0 )
904
0
    {
905
0
        if( ( flags & SYMCRYPT_FLAG_ECKEY_ECDSA ) != 0 )
906
0
        {
907
            // Ensure ECDSA algorithm selftest is run before first use of ECDSA algorithm
908
0
            SYMCRYPT_RUN_SELFTEST_ONCE(
909
0
                SymCryptEcDsaSelftest,
910
0
                SYMCRYPT_SELFTEST_ALGORITHM_ECDSA );
911
0
        }
912
913
0
        if( ( flags & SYMCRYPT_FLAG_ECKEY_ECDH ) != 0 )
914
0
        {
915
            // Ensure we have run the algorithm selftest at least once.
916
0
            SYMCRYPT_RUN_SELFTEST_ONCE(
917
0
                SymCryptEcDhSecretAgreementSelftest,
918
0
                SYMCRYPT_SELFTEST_ALGORITHM_ECDH );
919
920
            // Run PCT eagerly so it only needs to be defined here
921
            // The important case for performance is ECDH key generation
922
923
            // ECDH PCT per SP80056a-rev3 5.6.2.1.4 b)
924
            // Recompute the public key from the private key
925
            // Option a) appears to be explicitly overruled by 140-3 IG
926
0
            pbScratchInternal = pbScratch;
927
0
            cbScratchInternal = cbScratch;
928
929
0
            cbTmp = SymCryptSizeofEcpointFromCurve( pCurve );
930
0
            poTmp = SymCryptEcpointCreate( pbScratchInternal, cbTmp, pCurve );
931
0
            pbScratchInternal += cbTmp;
932
0
            cbScratchInternal -= cbTmp;
933
            
934
0
            SYMCRYPT_ASSERT( poTmp != NULL );
935
936
            // Always multiply by the cofactor since the internal format is "DIVH"
937
0
            scError = SymCryptEcpointScalarMul(
938
0
                pCurve,
939
0
                pEckey->piPrivateKey,
940
0
                NULL,
941
0
                SYMCRYPT_FLAG_ECC_LL_COFACTOR_MUL,
942
0
                poTmp,
943
0
                pbScratchInternal,
944
0
                cbScratchInternal );
945
0
            if ( scError != SYMCRYPT_NO_ERROR )
946
0
            {
947
0
                goto cleanup;
948
0
            }
949
950
0
            SYMCRYPT_FIPS_ASSERT( SymCryptEcpointIsEqual( pCurve, poTmp, pEckey->poPublicKey, 0, pbScratchInternal, cbScratchInternal ) );
951
0
        }
952
0
    }
953
954
0
cleanup:
955
956
0
    if ( pbScratch != NULL )
957
0
    {
958
0
        SymCryptWipe( pbScratch, cbScratch );
959
0
        SymCryptCallbackFree( pbScratch );
960
0
    }
961
962
0
    return scError;
963
0
}
964
965
SYMCRYPT_ERROR
966
SYMCRYPT_CALL
967
SymCryptEckeyExtendKeyUsage(
968
    _Inout_ PSYMCRYPT_ECKEY pEckey,
969
            UINT32          flags )
970
0
{
971
0
    SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
972
973
    // Ensure caller has specified what algorithm(s) the key will be used with
974
0
    UINT32 algorithmFlags = SYMCRYPT_FLAG_ECKEY_ECDSA | SYMCRYPT_FLAG_ECKEY_ECDH;
975
976
0
    if ( ( ( flags & ~algorithmFlags ) != 0 ) ||
977
0
         ( ( flags & algorithmFlags ) == 0) )
978
0
    {
979
0
        scError = SYMCRYPT_INVALID_ARGUMENT;
980
0
        goto cleanup;
981
0
    }
982
983
0
    pEckey->fAlgorithmInfo |= flags;
984
985
0
cleanup:
986
0
    return scError;
987
0
}