There is no known practical attack against your system, but it can not be proven secure by assuming only that SHA-256 meets its stated design goals (collision and preimage resistance). For more assurance, you could use a MAC, with master key as the key, and UID as the message. While HMAC_SHA-256 can not be proven secure under the above assumptions on SHA-256, it has more security margin than your scheme, and a security argument.
–
fgrieuApr 7 '12 at 8:53

Ah! You just helped me understand things a little better. A KDF becomes an HMAC when padding is added to guard against extension attacks. Since I don't need to authenticate the key (and the key is never stored) the padding is optional. However, I can understand why HMACs are recommened for KDF since they are also KDFs.
–
Grant BlahaErathApr 8 '12 at 4:30

2 Answers
2

Expert cryptographers will give you grief and tell you that you should be using a PRF, and technically speaking, they will be right. So, if you want to spare yourself from having that conversation, replace SHA256 with a PRF, such as AES-CMAC or SHA256-HMAC or PBKDF2 (using the master key as the key and the uuid as the seed). This is the technically proper way to do it, and I'm thoroughly sympathetic with those who argue you should do it this way.

That said, even if you went ahead and used your original proposal (SHA256), you'd almost certainly be fine. So, if I saw you using SHA256 instead of a PRF, I wouldn't get too worried about it.

P.S. I see a lot of confusion in the comments. The following are not identical: PRF, MAC, HMAC.

The SHA-256 compression function compress a 256-bit chaining value and
a 512-message block to an 256-bit output value. Let us assume that it
is secure, i.e., collision and preimage resistance.

Then, you should at first hash the 512-bit master key
and then then 128-bit uuid, since the first invocation compress the
512-bit master key and the 256-bit initial state to an unpredictable
256-bit chaining value X. In the following and final compression
function call, X and the padded uuid is compressed to an 256-bit
output value Y. Here, the unpredictability of X implies the
unpredictability of Y.

SHA-256(master key | uuid) should do the trick, iff the internal
compression function is ideal. Nevertheless, the construction looks
a little bit fragile to me, since the SHA-256 compression function is
most likely not ideal and the uuids only differ in a few bits.
Therefore, I would recommend a much more conservative approach like
SHA-256(master key | uuid | SHA-256(uuid)). In addition, you can increase
the number of SHA-256 rounds, i.e., double or triple them.