(req *Request)
| 79 | } |
| 80 | |
| 81 | func (e encryptedModel) Request(req *Request) (RequestResponse, error) { |
| 82 | folderKey, ok := e.folderKeys.get(req.Folder) |
| 83 | if !ok { |
| 84 | return e.model.Request(req) |
| 85 | } |
| 86 | |
| 87 | // Figure out the real file name, offset and size from the encrypted / |
| 88 | // tweaked values. |
| 89 | |
| 90 | realName, err := decryptName(req.Name, folderKey) |
| 91 | if err != nil { |
| 92 | return nil, fmt.Errorf("decrypting name: %w", err) |
| 93 | } |
| 94 | realSize := req.Size - blockOverhead |
| 95 | realOffset := req.Offset - int64(req.BlockNo*blockOverhead) |
| 96 | |
| 97 | if req.Size < minPaddedSize { |
| 98 | return nil, errors.New("short request") |
| 99 | } |
| 100 | |
| 101 | // Attempt to decrypt the block hash; it may be nil depending on what |
| 102 | // type of device the request comes from. Trusted devices with |
| 103 | // encryption enabled know the hash but don't bother to encrypt & send |
| 104 | // it to us. Untrusted devices have the hash from the encrypted index |
| 105 | // data and do send it. The model knows to only verify the hash if it |
| 106 | // actually gets one. |
| 107 | |
| 108 | var realHash []byte |
| 109 | fileKey := e.keyGen.FileKey(realName, folderKey) |
| 110 | if len(req.Hash) > 0 { |
| 111 | var additional [8]byte |
| 112 | binary.BigEndian.PutUint64(additional[:], uint64(realOffset)) |
| 113 | realHash, err = decryptDeterministic(req.Hash, fileKey, additional[:]) |
| 114 | if err != nil { |
| 115 | // "Legacy", no offset additional data? |
| 116 | realHash, err = decryptDeterministic(req.Hash, fileKey, nil) |
| 117 | } |
| 118 | if err != nil { |
| 119 | return nil, fmt.Errorf("decrypting block hash: %w", err) |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | // Perform that request and grab the data. |
| 124 | |
| 125 | req.Name = realName |
| 126 | req.Size = realSize |
| 127 | req.Offset = realOffset |
| 128 | req.Hash = realHash |
| 129 | resp, err := e.model.Request(req) |
| 130 | if err != nil { |
| 131 | return nil, err |
| 132 | } |
| 133 | |
| 134 | // Encrypt the response. Blocks smaller than minPaddedSize are padded |
| 135 | // with random data. |
| 136 | |
| 137 | data := resp.Data() |
| 138 | if len(data) < minPaddedSize { |
nothing calls this directly
no test coverage detected