SMP_FLAG_COMPLETE,
        SMP_FLAG_INITIATOR,
        SMP_FLAG_SC,
+       SMP_FLAG_REMOTE_PK,
 };
 
 struct smp_chan {
        /* Secure Connections variables */
        u8                      local_pk[64];
        u8                      local_sk[32];
+       u8                      remote_pk[64];
+       u8                      dhkey[32];
 
        struct crypto_blkcipher *tfm_aes;
        struct crypto_hash      *tfm_cmac;
        return 0;
 }
 
+static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+       struct smp_cmd_public_key *key = (void *) skb->data;
+       struct hci_conn *hcon = conn->hcon;
+       struct l2cap_chan *chan = conn->smp;
+       struct smp_chan *smp = chan->data;
+       int err;
+
+       BT_DBG("conn %p", conn);
+
+       if (skb->len < sizeof(*key))
+               return SMP_INVALID_PARAMS;
+
+       memcpy(smp->remote_pk, key, 64);
+
+       /* Non-initiating device sends its public key after receiving
+        * the key from the initiating device.
+        */
+       if (!hcon->out) {
+               err = sc_send_public_key(smp);
+               if (err)
+                       return err;
+       }
+
+       BT_DBG("Remote Public Key X: %32phN", smp->remote_pk);
+       BT_DBG("Remote Public Key Y: %32phN", &smp->remote_pk[32]);
+
+       if (!ecdh_shared_secret(smp->remote_pk, smp->local_sk, smp->dhkey))
+               return SMP_UNSPECIFIED;
+
+       BT_DBG("DHKey %32phN", smp->dhkey);
+
+       set_bit(SMP_FLAG_REMOTE_PK, &smp->flags);
+
+       return 0;
+}
+
 static int smp_sig_channel(struct l2cap_chan *chan, struct sk_buff *skb)
 {
        struct l2cap_conn *conn = chan->conn;
                reason = smp_cmd_sign_info(conn, skb);
                break;
 
+       case SMP_CMD_PUBLIC_KEY:
+               reason = smp_cmd_public_key(conn, skb);
+               break;
+
        default:
                BT_DBG("Unknown command code 0x%2.2x", code);
                reason = SMP_CMD_NOTSUPP;