(ctx context.Context, plainBR blob.Ref)
| 202 | } |
| 203 | |
| 204 | func (s *storage) Fetch(ctx context.Context, plainBR blob.Ref) (io.ReadCloser, uint32, error) { |
| 205 | plainSize, encBR, err := s.fetchMeta(ctx, plainBR) |
| 206 | if err != nil { |
| 207 | return nil, 0, err |
| 208 | } |
| 209 | encData, _, err := s.blobs.Fetch(ctx, encBR) |
| 210 | if err != nil { |
| 211 | return nil, 0, fmt.Errorf("encrypt: error fetching plaintext %s's encrypted %v blob: %v", plainBR, encBR, err) |
| 212 | } |
| 213 | defer encData.Close() |
| 214 | |
| 215 | encBytes := pools.BytesBuffer() |
| 216 | defer pools.PutBuffer(encBytes) |
| 217 | |
| 218 | encHash := encBR.Hash() |
| 219 | _, err = io.Copy(io.MultiWriter(encBytes, encHash), encData) |
| 220 | if err != nil { |
| 221 | return nil, 0, err |
| 222 | } |
| 223 | |
| 224 | // We have a signed statement in the meta blob that attests that the |
| 225 | // ciphertext hash corresponds to the plaintext hash, so no need to check |
| 226 | // the latter. However, check the former to make sure the encrypted blob |
| 227 | // was not swapped for another. |
| 228 | if !encBR.HashMatches(encHash) { |
| 229 | return nil, 0, blobserver.ErrCorruptBlob |
| 230 | } |
| 231 | |
| 232 | // Using the pool here would be racy since the caller will read this asynchronously |
| 233 | plainBytes := bytes.NewBuffer(nil) |
| 234 | if err := s.decryptBlob(plainBytes, encBytes); err != nil { |
| 235 | return nil, 0, fmt.Errorf("encrypt: encrypted blob %s failed validation: %s", encBR, err) |
| 236 | } |
| 237 | |
| 238 | return io.NopCloser(plainBytes), plainSize, nil |
| 239 | } |
| 240 | |
| 241 | func (s *storage) EnumerateBlobs(ctx context.Context, dest chan<- blob.SizedRef, after string, limit int) error { |
| 242 | defer close(dest) |
nothing calls this directly
no test coverage detected