@@ -162,12 +162,14 @@ func TestPostgresStores_Live(t *testing.T) {
162162 // embedded NULs and high bytes, to exercise real byte round-trips.
163163 liveFEEParams := func (space did.DID , d []byte ) registry.BlobEncryptionParams {
164164 return registry.BlobEncryptionParams {
165- Space : space ,
166- Digest : d ,
167- HeaderLen : 212 ,
168- BaseNonce : []byte {0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 },
169- ChunkSize : 65536 ,
170- AAD : []byte {0xa1 , 0x00 , 0x18 , 0x20 },
165+ Space : space ,
166+ Digest : d ,
167+ RegionWrappedCEK : []byte {0xde , 0xad , 0x00 , 0xbe , 0xef , 0xff },
168+ RegionKeyVersion : "region-kek-v1" ,
169+ HeaderLen : 212 ,
170+ BaseNonce : []byte {0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 },
171+ ChunkSize : 65536 ,
172+ AAD : []byte {0xa1 , 0x00 , 0x18 , 0x20 },
171173 }
172174 }
173175
@@ -201,18 +203,66 @@ func TestPostgresStores_Live(t *testing.T) {
201203 }
202204 })
203205
206+ t .Run ("encryption params rewrap in place" , func (t * testing.T ) {
207+ // A rotation replaces only the wrapped CEK and its key version; the
208+ // parameters describing the unchanged ciphertext must survive.
209+ space := testutil .RandomDID (t )
210+ encDigest := []byte {0x0a , 0x0b }
211+ if err := r .PutEncryptionParams (ctx , liveFEEParams (space , encDigest )); err != nil {
212+ t .Fatalf ("PutEncryptionParams: %v" , err )
213+ }
214+ if err := r .RewrapEncryptionParams (ctx , space , encDigest , []byte {0xca , 0xfe , 0x00 , 0x01 }, "region-kek-v2" ); err != nil {
215+ t .Fatalf ("RewrapEncryptionParams: %v" , err )
216+ }
217+ got , err := r .GetEncryptionParams (ctx , space , encDigest )
218+ if err != nil {
219+ t .Fatalf ("GetEncryptionParams: %v" , err )
220+ }
221+ want := liveFEEParams (space , encDigest )
222+ want .RegionWrappedCEK = []byte {0xca , 0xfe , 0x00 , 0x01 }
223+ want .RegionKeyVersion = "region-kek-v2"
224+ if ! reflect .DeepEqual (* got , want ) {
225+ t .Fatalf ("after rewrap = %+v, want %+v" , * got , want )
226+ }
227+ })
228+
229+ t .Run ("encryption params rewrap of a missing row is ErrNotFound" , func (t * testing.T ) {
230+ space := testutil .RandomDID (t )
231+ err := r .RewrapEncryptionParams (ctx , space , []byte {0x0c }, []byte {0x01 }, "region-kek-v2" )
232+ if ! errors .Is (err , registry .ErrNotFound ) {
233+ t .Fatalf ("RewrapEncryptionParams(absent) = %v, want ErrNotFound" , err )
234+ }
235+ })
236+
204237 t .Run ("incomplete encryption params rejected" , func (t * testing.T ) {
205238 // The column constraints are the invariant: a half-populated set never
206239 // reaches the table.
207240 space := testutil .RandomDID (t )
208241 d := []byte {0x77 }
209- partial := liveFEEParams (space , d )
210- partial .AAD = nil
211- if err := r .PutEncryptionParams (ctx , partial ); err == nil {
212- t .Fatal ("PutEncryptionParams(partial) = nil, want a constraint error" )
242+ for name , mutate := range map [string ]func (* registry.BlobEncryptionParams ){
243+ "nil AAD" : func (p * registry.BlobEncryptionParams ) { p .AAD = nil },
244+ "nil wrapped CEK" : func (p * registry.BlobEncryptionParams ) { p .RegionWrappedCEK = nil },
245+ "empty key version" : func (p * registry.BlobEncryptionParams ) { p .RegionKeyVersion = "" },
246+ } {
247+ partial := liveFEEParams (space , d )
248+ mutate (& partial )
249+ if err := r .PutEncryptionParams (ctx , partial ); err == nil {
250+ t .Fatalf ("PutEncryptionParams(%s) = nil, want a constraint error" , name )
251+ }
252+ if _ , err := r .GetEncryptionParams (ctx , space , d ); ! errors .Is (err , registry .ErrNotFound ) {
253+ t .Fatalf ("incomplete params (%s) leaked a row: %v" , name , err )
254+ }
255+ }
256+ // A rewrap cannot blank out the key material either.
257+ encDigest := []byte {0x78 }
258+ if err := r .PutEncryptionParams (ctx , liveFEEParams (space , encDigest )); err != nil {
259+ t .Fatalf ("PutEncryptionParams: %v" , err )
260+ }
261+ if err := r .RewrapEncryptionParams (ctx , space , encDigest , nil , "region-kek-v2" ); err == nil {
262+ t .Fatal ("RewrapEncryptionParams(nil CEK) = nil, want a constraint error" )
213263 }
214- if _ , err := r .GetEncryptionParams (ctx , space , d ); ! errors . Is ( err , registry . ErrNotFound ) {
215- t .Fatalf ( "incomplete params leaked a row: %v" , err )
264+ if err := r .RewrapEncryptionParams (ctx , space , encDigest , [] byte { 0x01 }, "" ); err == nil {
265+ t .Fatal ( "RewrapEncryptionParams(empty version) = nil, want a constraint error" )
216266 }
217267 })
218268
0 commit comments