@@ -4,11 +4,14 @@ package verification
4
4
5
5
import (
6
6
"bytes"
7
+ "crypto/ecdsa"
8
+ "crypto/elliptic"
7
9
"crypto/x509"
8
10
"encoding/asn1"
9
11
"encoding/binary"
10
12
"encoding/pem"
11
13
"fmt"
14
+ "math/big"
12
15
"reflect"
13
16
"testing"
14
17
"time"
@@ -117,18 +120,23 @@ const (
117
120
118
121
type TcgMultiTcbInfo = []DiceTcbInfo
119
122
123
+ type CertifyKeyParams struct {
124
+ Label []byte
125
+ Flags CertifyKeyFlags
126
+ }
127
+
120
128
func TestCertifyKey (d TestDPEInstance , c DPEClient , t * testing.T ) {
121
129
testCertifyKey (d , c , t , false )
122
130
}
123
131
124
- func TestCertifyKey_SimulationMode (d TestDPEInstance , c DPEClient , t * testing.T ) {
132
+ func TestCertifyKeySimulation (d TestDPEInstance , c DPEClient , t * testing.T ) {
125
133
testCertifyKey (d , c , t , true )
126
134
}
127
135
128
136
// Ignores critical extensions that are unknown to x509 package
129
137
// but atleast defined in DPE certificate profile specification.
130
138
// UnhandledCriticalExtensions may have only custom extensions mentioned in spec
131
- // unknownExtnMap collects extensions unknown to both x59 and the DICE certificate profiles spec.
139
+ // unknownExtnMap collects extensions unknown to both x509 and the DICE certificate profiles spec.
132
140
// positive case expects the unknownExtnMap to be empty.
133
141
func removeTcgDiceCriticalExtensions (t * testing.T , certs []* x509.Certificate ) {
134
142
t .Helper ()
@@ -158,6 +166,11 @@ func removeTcgDiceCriticalExtensions(t *testing.T, certs []*x509.Certificate) {
158
166
}
159
167
}
160
168
169
+ // Ignores extended key usages that are unknown to x509 package
170
+ // but atleast defined in DPE certificate profile specification.
171
+ // UnhandledExtendedKeyUsages may have only custom key usages mentioned in spec
172
+ // unknownKeyUsagesMap collects keyusages unknown to both x509 and the DICE certificate profiles spec.
173
+ // positive case expects the unknownKeyUsagesMap to be empty.
161
174
func removeTcgDiceExtendedKeyUsages (t * testing.T , certs []* x509.Certificate ) {
162
175
t .Helper ()
163
176
unknownKeyUsagesMap := map [string ][]string {}
@@ -218,7 +231,7 @@ func checkCertifyKeyTcgUeidExtension(t *testing.T, c *x509.Certificate, label []
218
231
}
219
232
}
220
233
221
- // Check whether certificate extended key usage is as per spec
234
+ // Checks whether certificate extended key usage is as per spec
222
235
// OID for ExtendedKeyUsage Extension: 2.5.29.37
223
236
// The ExtendedKeyUsage extension SHOULD be marked as critical
224
237
// If IsCA = true, the extension SHOULD contain tcg-dice-kp-eca
@@ -274,7 +287,7 @@ func checkCertifyKeyExtendedKeyUsages(t *testing.T, c *x509.Certificate) (*TcgMu
274
287
return multiTcbInfo , err
275
288
}
276
289
277
- // Check for KeyUsage Extension as per spec
290
+ // Checks for KeyUsage Extension as per spec
278
291
// If IsCA = true, KeyUsage extension MUST contain DigitalSignature and KeyCertSign
279
292
// If IsCA = false, KeyUsage extension MUST contain only DigitalSignature
280
293
func checkCertifyKeyExtensions (t * testing.T , c * x509.Certificate ) {
@@ -296,25 +309,25 @@ func checkCertifyKeyExtensions(t *testing.T, c *x509.Certificate) {
296
309
297
310
}
298
311
299
- // Validate basic constraints in certificate returned by CertifyKey command
312
+ // Validates basic constraints in certificate returned by CertifyKey command
300
313
// against the flag set for input parameter.
301
314
// The BasicConstraints extension MUST be included
302
315
// If CertifyKey AddIsCA is set, IsCA MUST be set to true.
303
316
// If CertifyKey AddIsCA is NOT set, IsCA MUST be set to false
304
- func checkCertifyKeyBasicConstraints (t * testing.T , c * x509.Certificate , flags uint32 ) {
317
+ func checkCertifyKeyBasicConstraints (t * testing.T , c * x509.Certificate , flags CertifyKeyFlags ) {
305
318
t .Helper ()
306
319
307
320
flagsBuf := & bytes.Buffer {}
308
321
binary .Write (flagsBuf , binary .LittleEndian , flags )
309
322
310
- flagIsCA := uint32 ( CertifyAddIsCA ) & flags != 0
323
+ flagIsCA := CertifyAddIsCA & flags != 0
311
324
if flagIsCA != c .IsCA {
312
325
t .Errorf ("[ERROR]: ADD_IS_CA is set to %v but the basic constraint IsCA is set to %v" , flagIsCA , c .IsCA )
313
326
}
314
327
}
315
328
316
- // Validate X509 fields in certificate returned by CertifyKey command.
317
- func validateCertifyKeyCert (t * testing.T , c * x509.Certificate , flags uint32 , label []byte ) {
329
+ // Validates X509 fields in certificate returned by CertifyKey command.
330
+ func validateCertifyKeyCert (t * testing.T , c * x509.Certificate , flags CertifyKeyFlags , label []byte ) {
318
331
t .Helper ()
319
332
320
333
// Check for basic constraints extension
@@ -337,6 +350,7 @@ func validateCertifyKeyCert(t *testing.T, c *x509.Certificate, flags uint32, lab
337
350
}
338
351
}
339
352
353
+ // Parses X509 certificate
340
354
func checkCertificateStructure (t * testing.T , certBytes []byte ) * x509.Certificate {
341
355
t .Helper ()
342
356
failed := false
@@ -411,44 +425,48 @@ func checkCertificateStructure(t *testing.T, certBytes []byte) *x509.Certificate
411
425
return x509Cert
412
426
}
413
427
414
- func testCertifyKey (d TestDPEInstance , client DPEClient , t * testing.T , simulation bool ) {
415
- ctx := getInitialContextHandle (d , client , t , simulation )
428
+ func testCertifyKey (d TestDPEInstance , c DPEClient , t * testing.T , simulation bool ) {
429
+ handle := getInitialContextHandle (d , c , t , simulation )
416
430
defer func () {
417
431
if simulation {
418
- client .DestroyContext (ctx , DestroyDescendants )
432
+ c .DestroyContext (handle , DestroyDescendants )
419
433
}
420
434
}()
421
435
422
- type Params struct {
423
- Label []byte
424
- Flags CertifyKeyFlags
425
- }
426
-
427
436
profile , err := GetTransportProfile (d )
428
437
if err != nil {
429
438
t .Fatalf ("Could not get profile: %v" , err )
430
439
}
431
440
digestLen := profile .GetDigestSize ()
432
441
442
+ var hashAlg asn1.ObjectIdentifier
443
+ if digestLen == 32 {
444
+ hashAlg = OidSHA256
445
+ } else if digestLen == 48 {
446
+ hashAlg = OidSHA384
447
+ } else {
448
+ t .Fatal ("Unknown Hash Algorithm" )
449
+ }
450
+
433
451
seqLabel := make ([]byte , digestLen )
434
452
for i := range seqLabel {
435
453
seqLabel [i ] = byte (i )
436
454
}
437
455
438
- certifyKeyParams := []Params {
456
+ certifyKeyParams := []CertifyKeyParams {
439
457
{Label : make ([]byte , digestLen ), Flags : CertifyKeyFlags (0 )},
440
458
{Label : seqLabel , Flags : CertifyKeyFlags (0 )},
441
459
}
442
460
443
461
for _ , params := range certifyKeyParams {
444
462
// Get DPE leaf certificate from CertifyKey
445
- certifyKeyResp , err := client .CertifyKey (ctx , params .Label , CertifyKeyX509 , params .Flags )
463
+ certifyKeyResp , err := c .CertifyKey (handle , params .Label , CertifyKeyX509 , params .Flags )
446
464
if err != nil {
447
465
t .Fatalf ("[FATAL]: Could not certify key: %v" , err )
448
466
}
449
467
450
468
// Get root and intermediate certificates to validate certificate chain of leaf cert
451
- certChainBytes , err := client .GetCertificateChain ()
469
+ certChainBytes , err := c .GetCertificateChain ()
452
470
if err != nil {
453
471
t .Fatalf ("[FATAL]: Could not get Certificate Chain: %v" , err )
454
472
}
@@ -459,8 +477,14 @@ func testCertifyKey(d TestDPEInstance, client DPEClient, t *testing.T, simulatio
459
477
leafCert := checkCertificateStructure (t , leafCertBytes )
460
478
certChain := checkCertificateChain (t , certChainBytes )
461
479
480
+ // Check default context handle is unchanged
481
+ checkCertifyKeyRespHandle (* certifyKeyResp , t , handle )
482
+
483
+ // Check key returned in command response against certificate
484
+ checkCertifyKeyResponse (t , leafCert , * certifyKeyResp , hashAlg )
485
+
462
486
// Validate that all X.509 fields conform with the format defined in the DPE iRoT profile
463
- validateCertifyKeyCert (t , leafCert , uint32 ( params .Flags ) , params .Label )
487
+ validateCertifyKeyCert (t , leafCert , params .Flags , params .Label )
464
488
465
489
// Ensure full certificate chain has valid signatures
466
490
// This also checks certificate lifetime, signatures as part of cert chain validation
@@ -469,13 +493,12 @@ func testCertifyKey(d TestDPEInstance, client DPEClient, t *testing.T, simulatio
469
493
// Reassign handle for simulation mode.
470
494
// However, this does not impact in default mode because
471
495
// same default context handle is returned in default mode.
472
- ctx = & certifyKeyResp .Handle
473
-
474
- // TODO: When DeriveChild is implemented, call it here to add more TCIs and call CertifyKey again.
496
+ handle = & certifyKeyResp .Handle
475
497
}
498
+ // TODO: When DeriveChild is implemented, call it here to add more TCIs and call CertifyKey again.
476
499
}
477
500
478
- // Build certificate chain and calls to validateSignature on each chain.
501
+ // Builds and verifies certificate chain.
479
502
func validateLeafCertChain (t * testing.T , certChain []* x509.Certificate , leafCert * x509.Certificate ) {
480
503
t .Helper ()
481
504
certsToProcess := []* x509.Certificate {leafCert }
@@ -502,6 +525,7 @@ func validateLeafCertChain(t *testing.T, certChain []*x509.Certificate, leafCert
502
525
}
503
526
}
504
527
528
+ // Builds Certificate chain verifier parameters.
505
529
func buildVerifyOptions (t * testing.T , certChain []* x509.Certificate ) x509.VerifyOptions {
506
530
roots := x509 .NewCertPool ()
507
531
intermediates := x509 .NewCertPool ()
@@ -526,6 +550,7 @@ func buildVerifyOptions(t *testing.T, certChain []*x509.Certificate) x509.Verify
526
550
return opts
527
551
}
528
552
553
+ // Gets KeyUsage bitmap and returns as list of KeyUsage name strings.
529
554
func getKeyUsageNames (keyUsage x509.KeyUsage ) []string {
530
555
keyUsageNames := []string {}
531
556
@@ -567,3 +592,58 @@ func getKeyUsageNames(keyUsage x509.KeyUsage) []string {
567
592
568
593
return keyUsageNames
569
594
}
595
+
596
+ // Checks CertifyKey command response against public key extracted from certificate returned in response
597
+ func checkCertifyKeyResponse (t * testing.T , x509Cert * x509.Certificate , response CertifiedKey , hashAlg asn1.ObjectIdentifier ) {
598
+ var err error
599
+
600
+ publicKeyDer , err := x509 .MarshalPKIXPublicKey (x509Cert .PublicKey )
601
+ if err != nil {
602
+ t .Fatalf ("[FATAL]: Could not marshal pub key: %v" , err )
603
+ }
604
+
605
+ // Parse the DER-encoded public key
606
+ pubKeyInCert , err := x509 .ParsePKIXPublicKey (publicKeyDer )
607
+ if err != nil {
608
+ t .Fatalf ("[FATAL]: Failed to parse DER-encoded public key: %v" , err )
609
+ }
610
+
611
+ if _ , ok := pubKeyInCert .(* ecdsa.PublicKey ); ! ok {
612
+ t .Fatal ("[FATAL]: Public key is not a ecdsa key" )
613
+ }
614
+
615
+ var pubKeyInResponse ecdsa.PublicKey
616
+
617
+ if hashAlg .Equal (OidSHA384 ) {
618
+ pubKeyInResponse = ecdsa.PublicKey {
619
+ Curve : elliptic .P384 (),
620
+ X : new (big.Int ).SetBytes (response .Pub .X ),
621
+ Y : new (big.Int ).SetBytes (response .Pub .Y ),
622
+ }
623
+ } else if hashAlg .Equal (OidSHA256 ) {
624
+ pubKeyInResponse = ecdsa.PublicKey {
625
+ Curve : elliptic .P256 (),
626
+ X : new (big.Int ).SetBytes (response .Pub .X ),
627
+ Y : new (big.Int ).SetBytes (response .Pub .Y ),
628
+ }
629
+ } else {
630
+ t .Errorf ("[ERROR]: Unsupported hash algorithm." )
631
+ return
632
+ }
633
+
634
+ if ! (pubKeyInResponse .Equal (pubKeyInCert )) {
635
+ t .Errorf ("[ERROR]: Public key returned in response must match the Public Key Info in the certificate." )
636
+ }
637
+ }
638
+
639
+ // Checks whether the context handle is unchanged after certifyKey command when default context handle is used.
640
+ func checkCertifyKeyRespHandle (res CertifiedKey , t * testing.T , handle * ContextHandle ) {
641
+ if * handle != DefaultContextHandle {
642
+ t .Logf ("[LOG]: Handle is not default context, skipping check..." )
643
+ return
644
+ }
645
+
646
+ if res .Handle != * handle {
647
+ t .Errorf ("[ERROR]: Handle must be unchanged by CertifyKey, want original handle %v but got %v" , handle , res .Handle )
648
+ }
649
+ }
0 commit comments