If you dive into the source code of class BertSelfAttention(nn.Module) you will find:
    self.num_attention_heads = config.num_attention_heads
    self.attention_head_size = int(config.hidden_size / config.num_attention_heads)
    self.all_head_size = self.num_attention_heads * self.attention_head_size

    self.query = nn.Linear(config.hidden_size, self.all_head_size)
    self.key = nn.Linear(config.hidden_size, self.all_head_size)
    self.value = nn.Linear(config.hidden_size, self.all_head_size)

In my view, this illustrates that the size of Q, K and V in a single head is actually 768 x 64 if the number of heads is 12. Due to the multi-head attention these are later concatenated to again produce the abovementioned shape of 768 x 768 which you have obeserved.