@@ -61,7 +61,8 @@ type NanoTDFHeader struct {
61
61
bindCfg bindingConfig
62
62
sigCfg signatureConfig
63
63
EphemeralKey []byte
64
- EncryptedPolicyBody []byte
64
+ PolicyMode PolicyType
65
+ PolicyBody []byte
65
66
gmacPolicyBinding []byte
66
67
ecdsaPolicyBindingR []byte
67
68
ecdsaPolicyBindingS []byte
@@ -90,7 +91,7 @@ func (header *NanoTDFHeader) VerifyPolicyBinding() (bool, error) {
90
91
return false , err
91
92
}
92
93
93
- digest := ocrypto .CalculateSHA256 (header .EncryptedPolicyBody )
94
+ digest := ocrypto .CalculateSHA256 (header .PolicyBody )
94
95
if header .IsEcdsaBindingEnabled () {
95
96
ephemeralECDSAPublicKey , err := ocrypto .UncompressECPubKey (curve , header .EphemeralKey )
96
97
if err != nil {
@@ -499,14 +500,15 @@ func writeNanoTDFHeader(writer io.Writer, config NanoTDFConfig) ([]byte, uint32,
499
500
}
500
501
totalBytes += uint32 (l )
501
502
502
- // Write policy - (Policy Mode, Policy length, Policy cipherText, Policy binding)
503
- config .policy .body .mode = policyTypeEmbeddedPolicyEncrypted
503
+ // Write policy mode
504
+ config .policy .body .mode = config . policyMode
504
505
l , err = writer .Write ([]byte {byte (config .policy .body .mode )})
505
506
if err != nil {
506
507
return nil , 0 , 0 , err
507
508
}
508
509
totalBytes += uint32 (l )
509
510
511
+ // Create policy object
510
512
policyObj , err := createPolicyObject (config .attributes )
511
513
if err != nil {
512
514
return nil , 0 , 0 , fmt .Errorf ("fail to create policy object:%w" , err )
@@ -517,59 +519,34 @@ func writeNanoTDFHeader(writer io.Writer, config NanoTDFConfig) ([]byte, uint32,
517
519
return nil , 0 , 0 , fmt .Errorf ("json.Marshal failed:%w" , err )
518
520
}
519
521
520
- ecdhKey , err := ocrypto .ConvertToECDHPrivateKey (config .keyPair .PrivateKey )
522
+ // Create the symmetric key
523
+ symmetricKey , err := createNanoTDFSymmetricKey (config )
521
524
if err != nil {
522
- return nil , 0 , 0 , fmt .Errorf ("ocrypto.ConvertToECDHPrivateKey failed:%w" , err )
523
- }
524
-
525
- symKey , err := ocrypto .ComputeECDHKeyFromECDHKeys (config .kasPublicKey , ecdhKey )
526
- if err != nil {
527
- return nil , 0 , 0 , fmt .Errorf ("ocrypto.ComputeECDHKeyFromEC failed:%w" , err )
528
- }
529
-
530
- salt := versionSalt ()
531
-
532
- symmetricKey , err := ocrypto .CalculateHKDF (salt , symKey )
533
- if err != nil {
534
- return nil , 0 , 0 , fmt .Errorf ("ocrypto.CalculateHKDF failed:%w" , err )
535
- }
536
-
537
- aesGcm , err := ocrypto .NewAESGcm (symmetricKey )
538
- if err != nil {
539
- return nil , 0 , 0 , fmt .Errorf ("ocrypto.NewAESGcm failed:%w" , err )
525
+ return nil , 0 , 0 , err
540
526
}
541
527
542
- tagSize , err := SizeOfAuthTagForCipher ( config . sigCfg . cipher )
543
- if err != nil {
544
- return nil , 0 , 0 , fmt . Errorf ( "SizeOfAuthTagForCipher failed:%w" , err )
528
+ // Set the symmetric key in the collection config
529
+ if config . collectionCfg . useCollection {
530
+ config . collectionCfg . symKey = symmetricKey
545
531
}
546
532
547
- const (
548
- kIvLength = 12
549
- )
550
- iv := make ([]byte , kIvLength )
551
- cipherText , err := aesGcm .EncryptWithIVAndTagSize (iv , policyObjectAsStr , tagSize )
533
+ embeddedP , err := createNanoTDFEmbeddedPolicy (symmetricKey , policyObjectAsStr , config )
552
534
if err != nil {
553
- return nil , 0 , 0 , fmt .Errorf ("AesGcm.EncryptWithIVAndTagSize failed:%w" , err )
535
+ return nil , 0 , 0 , fmt .Errorf ("failed to create embedded policy :%w" , err )
554
536
}
555
537
556
- embeddedP := embeddedPolicy {
557
- lengthBody : uint16 (len (cipherText ) - len (iv )),
558
- body : cipherText [len (iv ):],
559
- }
560
538
err = embeddedP .writeEmbeddedPolicy (writer )
561
539
if err != nil {
562
540
return nil , 0 , 0 , fmt .Errorf ("writeEmbeddedPolicy failed:%w" , err )
563
541
}
564
542
565
543
// size of uint16
566
- const (
567
- kSizeOfUint16 = 2
568
- )
544
+ const kSizeOfUint16 = 2
569
545
totalBytes += kSizeOfUint16 + uint32 (len (embeddedP .body ))
570
546
571
547
digest := ocrypto .CalculateSHA256 (embeddedP .body )
572
- if config .bindCfg .useEcdsaBinding { //nolint:nestif // todo: subfunction
548
+
549
+ if config .bindCfg .useEcdsaBinding { //nolint:nestif // TODO: refactor
573
550
rBytes , sBytes , err := ocrypto .ComputeECDSASig (digest , config .keyPair .PrivateKey )
574
551
if err != nil {
575
552
return nil , 0 , 0 , fmt .Errorf ("ComputeECDSASig failed:%w" , err )
@@ -617,19 +594,15 @@ func writeNanoTDFHeader(writer io.Writer, config NanoTDFConfig) ([]byte, uint32,
617
594
}
618
595
totalBytes += uint32 (l )
619
596
620
- if config .collectionCfg .useCollection {
621
- config .collectionCfg .symKey = symmetricKey
622
- }
623
-
624
597
return symmetricKey , totalBytes , 0 , nil
625
598
}
626
599
627
600
func NewNanoTDFHeaderFromReader (reader io.Reader ) (NanoTDFHeader , uint32 , error ) {
628
601
header := NanoTDFHeader {}
629
602
var size uint32
630
603
604
+ // Read and validate magic number
631
605
magicNumber := make ([]byte , len (kNanoTDFMagicStringAndVersion ))
632
-
633
606
l , err := reader .Read (magicNumber )
634
607
if err != nil {
635
608
return header , 0 , fmt .Errorf (" io.Reader.Read failed :%w" , err )
@@ -643,7 +616,7 @@ func NewNanoTDFHeaderFromReader(reader io.Reader) (NanoTDFHeader, uint32, error)
643
616
return header , 0 , errors .New ("not a valid nano tdf" )
644
617
}
645
618
646
- // read resource locator
619
+ // Read resource locator
647
620
resource , err := NewResourceLocatorFromReader (reader )
648
621
if err != nil {
649
622
return header , 0 , fmt .Errorf ("call to NewResourceLocatorFromReader failed :%w" , err )
@@ -653,7 +626,7 @@ func NewNanoTDFHeaderFromReader(reader io.Reader) (NanoTDFHeader, uint32, error)
653
626
654
627
slog .Debug ("NewNanoTDFHeaderFromReader" , slog .Uint64 ("resource locator" , uint64 (resource .getLength ())))
655
628
656
- // read ECC and Binding Mode
629
+ // Read ECC and Binding Mode
657
630
oneBytes := make ([]byte , 1 )
658
631
l , err = reader .Read (oneBytes )
659
632
if err != nil {
@@ -662,12 +635,12 @@ func NewNanoTDFHeaderFromReader(reader io.Reader) (NanoTDFHeader, uint32, error)
662
635
size += uint32 (l )
663
636
header .bindCfg = deserializeBindingCfg (oneBytes [0 ])
664
637
665
- // check ephemeral ECC Params Enum
638
+ // Check ephemeral ECC Params Enum
666
639
if header .bindCfg .eccMode != ocrypto .ECCModeSecp256r1 {
667
640
return header , 0 , errors .New ("current implementation of nano tdf only support secp256r1 curve" )
668
641
}
669
642
670
- // read Payload and Sig Mode
643
+ // Read Payload and Sig Mode
671
644
l , err = reader .Read (oneBytes )
672
645
if err != nil {
673
646
return header , 0 , fmt .Errorf (" io.Reader.Read failed :%w" , err )
@@ -682,14 +655,13 @@ func NewNanoTDFHeaderFromReader(reader io.Reader) (NanoTDFHeader, uint32, error)
682
655
}
683
656
size += uint32 (l )
684
657
685
- if oneBytes [0 ] != uint8 (policyTypeEmbeddedPolicyEncrypted ) {
686
- return header , 0 , errors .New (" current implementation only support embedded policy type" )
658
+ policyMode := PolicyType (oneBytes [0 ])
659
+ if err := validNanoTDFPolicyMode (policyMode ); err != nil {
660
+ return header , 0 , errors .Join (fmt .Errorf ("unsupported policy mode: %v" , policyMode ), err )
687
661
}
688
662
689
- // read policy length
690
- const (
691
- kSizeOfUint16 = 2
692
- )
663
+ // Read policy length
664
+ const kSizeOfUint16 = 2
693
665
twoBytes := make ([]byte , kSizeOfUint16 )
694
666
l , err = reader .Read (twoBytes )
695
667
if err != nil {
@@ -699,17 +671,18 @@ func NewNanoTDFHeaderFromReader(reader io.Reader) (NanoTDFHeader, uint32, error)
699
671
policyLength := binary .BigEndian .Uint16 (twoBytes )
700
672
slog .Debug ("NewNanoTDFHeaderFromReader" , slog .Uint64 ("policyLength" , uint64 (policyLength )))
701
673
702
- // read policy body
703
- header .EncryptedPolicyBody = make ([]byte , policyLength )
704
- l , err = reader .Read (header .EncryptedPolicyBody )
674
+ // Read policy body
675
+ header .PolicyMode = policyMode
676
+ header .PolicyBody = make ([]byte , policyLength )
677
+ l , err = reader .Read (header .PolicyBody )
705
678
if err != nil {
706
679
return header , 0 , fmt .Errorf (" io.Reader.Read failed :%w" , err )
707
680
}
708
681
size += uint32 (l )
709
682
710
- // read policy binding
711
- if header .bindCfg .useEcdsaBinding { //nolint:nestif // todo: subfunction
712
- // read rBytes len and its contents
683
+ // Read policy binding
684
+ if header .bindCfg .useEcdsaBinding { //nolint:nestif // TODO: refactor
685
+ // Read rBytes len and its contents
713
686
l , err = reader .Read (oneBytes )
714
687
if err != nil {
715
688
return header , 0 , fmt .Errorf (" io.Reader.Read failed :%w" , err )
@@ -723,7 +696,7 @@ func NewNanoTDFHeaderFromReader(reader io.Reader) (NanoTDFHeader, uint32, error)
723
696
}
724
697
size += uint32 (l )
725
698
726
- // read sBytes len and its contents
699
+ // Read sBytes len and its contents
727
700
l , err = reader .Read (oneBytes )
728
701
if err != nil {
729
702
return header , 0 , fmt .Errorf (" io.Reader.Read failed :%w" , err )
@@ -750,7 +723,7 @@ func NewNanoTDFHeaderFromReader(reader io.Reader) (NanoTDFHeader, uint32, error)
750
723
return header , 0 , fmt .Errorf ("getECCKeyLength :%w" , err )
751
724
}
752
725
753
- // read ephemeral Key
726
+ // Read ephemeral Key
754
727
ephemeralKey := make ([]byte , ephemeralKeySize )
755
728
l , err = reader .Read (ephemeralKey )
756
729
if err != nil {
@@ -995,8 +968,8 @@ func (n *NanoTDFDecryptHandler) Decrypt(_ context.Context, result []kaoResult) (
995
968
payloadLength := binary .BigEndian .Uint32 (payloadLengthBuf )
996
969
slog .Debug ("ReadNanoTDF" , slog .Uint64 ("payloadLength" , uint64 (payloadLength )))
997
970
998
- cipherDate := make ([]byte , payloadLength )
999
- _ , err = n .reader .Read (cipherDate )
971
+ cipherData := make ([]byte , payloadLength )
972
+ _ , err = n .reader .Read (cipherData )
1000
973
if err != nil {
1001
974
return 0 , fmt .Errorf ("readSeeker.Seek failed: %w" , err )
1002
975
}
@@ -1009,15 +982,15 @@ func (n *NanoTDFDecryptHandler) Decrypt(_ context.Context, result []kaoResult) (
1009
982
ivPadded := make ([]byte , 0 , ocrypto .GcmStandardNonceSize )
1010
983
noncePadding := make ([]byte , kIvPadding )
1011
984
ivPadded = append (ivPadded , noncePadding ... )
1012
- iv := cipherDate [:kNanoTDFIvSize ]
985
+ iv := cipherData [:kNanoTDFIvSize ]
1013
986
ivPadded = append (ivPadded , iv ... )
1014
987
1015
988
tagSize , err := SizeOfAuthTagForCipher (n .header .sigCfg .cipher )
1016
989
if err != nil {
1017
990
return 0 , fmt .Errorf ("SizeOfAuthTagForCipher failed:%w" , err )
1018
991
}
1019
992
1020
- decryptedData , err := aesGcm .DecryptWithIVAndTagSize (ivPadded , cipherDate [kNanoTDFIvSize :], tagSize )
993
+ decryptedData , err := aesGcm .DecryptWithIVAndTagSize (ivPadded , cipherData [kNanoTDFIvSize :], tagSize )
1021
994
if err != nil {
1022
995
return 0 , err
1023
996
}
@@ -1108,3 +1081,28 @@ func versionSalt() []byte {
1108
1081
digest .Write ([]byte (kNanoTDFMagicStringAndVersion ))
1109
1082
return digest .Sum (nil )
1110
1083
}
1084
+
1085
+ // createNanoTDFSymmetricKey creates the symmetric key for nanoTDF header
1086
+ func createNanoTDFSymmetricKey (config NanoTDFConfig ) ([]byte , error ) {
1087
+ if config .kasPublicKey == nil {
1088
+ return nil , fmt .Errorf ("KAS public key is required for encrypted policy mode" )
1089
+ }
1090
+
1091
+ ecdhKey , err := ocrypto .ConvertToECDHPrivateKey (config .keyPair .PrivateKey )
1092
+ if err != nil {
1093
+ return nil , fmt .Errorf ("ocrypto.ConvertToECDHPrivateKey failed:%w" , err )
1094
+ }
1095
+
1096
+ symKey , err := ocrypto .ComputeECDHKeyFromECDHKeys (config .kasPublicKey , ecdhKey )
1097
+ if err != nil {
1098
+ return nil , fmt .Errorf ("ocrypto.ComputeECDHKeyFromEC failed:%w" , err )
1099
+ }
1100
+
1101
+ salt := versionSalt ()
1102
+ symmetricKey , err := ocrypto .CalculateHKDF (salt , symKey )
1103
+ if err != nil {
1104
+ return nil , fmt .Errorf ("ocrypto.CalculateHKDF failed:%w" , err )
1105
+ }
1106
+
1107
+ return symmetricKey , nil
1108
+ }
0 commit comments