mesh: Convert crypto to use ELL wrappers
authorBrian Gix <brian.gix@intel.com>
Wed, 29 May 2019 17:28:18 +0000 (10:28 -0700)
committerAnupam Roy <anupam.r@samsung.com>
Tue, 17 Dec 2019 14:28:08 +0000 (19:58 +0530)
Use ELL implementations of aead-ccm(aes), ecb(aes) and cmac(aes). These
standard encryption and hashing routines are provided by ELL.

Change-Id: I4c82199cf8a58c6a09de8a8afcc74bb3cf584376
Signed-off-by: Anupam Roy <anupam.r@samsung.com>
mesh/crypto.c

index c8e3e21..18c6d43 100644 (file)
 /* Multiply used Zero array */
 static const uint8_t zero[16] = { 0, };
 
-static int alg_new(int fd, const void *keyval, socklen_t keylen,
-                                                       size_t mic_size)
+static bool aes_ecb_one(const uint8_t key[16], const uint8_t in[16],
+                                                               uint8_t out[16])
 {
-       if (setsockopt(fd, SOL_ALG, ALG_SET_KEY, keyval, keylen) < 0)
-               return -1;
+       void *cipher;
+       bool result = false;
 
-       if (mic_size &&
-               setsockopt(fd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE,
-                                                       NULL, mic_size) < 0)
-               return -1;
+       cipher = l_cipher_new(L_CIPHER_AES, key, 16);
 
-       /* FIXME: This should use accept4() with SOCK_CLOEXEC */
-       return accept(fd, NULL, 0);
-}
-
-static bool alg_encrypt(int fd, const void *inbuf, size_t inlen,
-                                               void *outbuf, size_t outlen)
-{
-       __u32 alg_op = ALG_OP_ENCRYPT;
-       char cbuf[CMSG_SPACE(sizeof(alg_op))];
-       struct cmsghdr *cmsg;
-       struct msghdr msg;
-       struct iovec iov;
-       ssize_t len;
-
-       memset(cbuf, 0, sizeof(cbuf));
-       memset(&msg, 0, sizeof(msg));
-
-       msg.msg_control = cbuf;
-       msg.msg_controllen = sizeof(cbuf);
-
-       cmsg = CMSG_FIRSTHDR(&msg);
-       cmsg->cmsg_level = SOL_ALG;
-       cmsg->cmsg_type = ALG_SET_OP;
-       cmsg->cmsg_len = CMSG_LEN(sizeof(alg_op));
-       memcpy(CMSG_DATA(cmsg), &alg_op, sizeof(alg_op));
-
-       iov.iov_base = (void *) inbuf;
-       iov.iov_len = inlen;
-
-       msg.msg_iov = &iov;
-       msg.msg_iovlen = 1;
-
-       len = sendmsg(fd, &msg, 0);
-       if (len < 0)
-               return false;
-
-       len = read(fd, outbuf, outlen);
-       if (len < 0)
-               return false;
-
-       return true;
-}
-
-static int aes_ecb_setup(const uint8_t key[16])
-{
-       struct sockaddr_alg salg;
-       int fd, nfd;
-
-       fd = socket(PF_ALG, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
-       if (fd < 0)
-               return -1;
-
-       memset(&salg, 0, sizeof(salg));
-       salg.salg_family = AF_ALG;
-       strcpy((char *) salg.salg_type, "skcipher");
-       strcpy((char *) salg.salg_name, "ecb(aes)");
-
-       if (bind(fd, (struct sockaddr *) &salg, sizeof(salg)) < 0) {
-               close(fd);
-               return -1;
+       if (cipher) {
+               result = l_cipher_encrypt(cipher, in, out, 16);
+               l_cipher_free(cipher);
        }
 
-       nfd = alg_new(fd, key, 16, 0);
-
-       close(fd);
-
-       return nfd;
-}
-
-static bool aes_ecb(int fd, const uint8_t plaintext[16], uint8_t encrypted[16])
-{
-       return alg_encrypt(fd, plaintext, 16, encrypted, 16);
-}
-
-static void aes_ecb_destroy(int fd)
-{
-       close(fd);
-}
-
-static bool aes_ecb_one(const uint8_t key[16],
-                       const uint8_t plaintext[16], uint8_t encrypted[16])
-{
-       bool result;
-       int fd;
-
-       fd = aes_ecb_setup(key);
-       if (fd < 0)
-               return false;
-
-       result = aes_ecb(fd, plaintext, encrypted);
-
-       aes_ecb_destroy(fd);
-
        return result;
 }
 
-bool mesh_aes_ecb_one(const uint8_t key[16],
-                       const uint8_t plaintext[16], uint8_t encrypted[16])
-{
-       return aes_ecb_one(key, plaintext, encrypted);
-}
-
-/* Maximum message length that can be passed to aes_cmac */
-#define CMAC_MSG_MAX   (64 + 64 + 17)
-
-static int aes_cmac_setup(const uint8_t key[16])
-{
-       struct sockaddr_alg salg;
-       int fd, nfd;
-
-       fd = socket(PF_ALG, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
-       if (fd < 0)
-               return -1;
-
-       memset(&salg, 0, sizeof(salg));
-       salg.salg_family = AF_ALG;
-       strcpy((char *) salg.salg_type, "hash");
-       strcpy((char *) salg.salg_name, "cmac(aes)");
-
-       if (bind(fd, (struct sockaddr *) &salg, sizeof(salg)) < 0) {
-               close(fd);
-               return -1;
-       }
-
-       nfd = alg_new(fd, key, 16, 0);
-
-       close(fd);
-
-       return nfd;
-}
-
-static bool aes_cmac(int fd, const uint8_t *msg,
+static bool aes_cmac(void *checksum, const uint8_t *msg,
                                        size_t msg_len, uint8_t res[16])
 {
-       ssize_t len;
-
-       if (msg_len > CMAC_MSG_MAX)
-               return false;
-
-       len = send(fd, msg, msg_len, 0);
-       if (len < 0)
-               return false;
-
-       len = read(fd, res, 16);
-       if (len < 0)
+       if (!l_checksum_update(checksum, msg, msg_len))
                return false;
 
-       return true;
-}
-
-static void aes_cmac_destroy(int fd)
-{
-       close(fd);
-}
-
-static int aes_cmac_N_start(const uint8_t N[16])
-{
-       int fd;
+       if (16 == l_checksum_get_digest(checksum, res, 16))
+               return true;
 
-       fd = aes_cmac_setup(N);
-       return fd;
+       return false;
 }
 
 static bool aes_cmac_one(const uint8_t key[16], const void *msg,
                                        size_t msg_len, uint8_t res[16])
 {
+       void *checksum;
        bool result;
-       int fd;
 
-       fd = aes_cmac_setup(key);
-       if (fd < 0)
+       checksum = l_checksum_new_cmac_aes(key, 16);
+       if (!checksum)
                return false;
 
-       result = aes_cmac(fd, msg, msg_len, res);
+       result = l_checksum_update(checksum, msg, msg_len);
 
-       aes_cmac_destroy(fd);
+       if (result) {
+               ssize_t len = l_checksum_get_digest(checksum, res, 16);
+               result = !!(len == 16);
+       }
+
+       l_checksum_free(checksum);
 
        return result;
 }
@@ -246,161 +105,22 @@ bool mesh_crypto_aes_ccm_encrypt(const uint8_t nonce[13], const uint8_t key[16],
                                        uint8_t *out_msg,
                                        void *out_mic, size_t mic_size)
 {
-       uint8_t pmsg[16], cmic[16], cmsg[16];
-       uint8_t mic[16], Xn[16];
-       uint16_t blk_cnt, last_blk;
+       void *cipher;
        bool result;
-       size_t i, j;
-       int fd;
-
-       /* Mesh limits AAD length to 16 */
-       if (aad_len > 16)
-               return false;
-
-       fd = aes_ecb_setup(key);
-       if (fd < 0)
-               return false;
-
-       /* C_mic = e(AppKey, 0x01 || nonce || 0x0000) */
-       pmsg[0] = 0x01;
-       memcpy(pmsg + 1, nonce, 13);
-       l_put_be16(0x0000, pmsg + 14);
-
-       result = aes_ecb(fd, pmsg, cmic);
-       if (!result)
-               goto done;
-
-       /* X_0 = e(AppKey, 0x09 || nonce || length) */
-       if (mic_size == 8)
-               pmsg[0] = 0x19 | (aad_len ? 0x40 : 0x00);
-       else
-               pmsg[0] = 0x09 | (aad_len ? 0x40 : 0x00);
-
-       memcpy(pmsg + 1, nonce, 13);
-       l_put_be16(msg_len, pmsg + 14);
-
-       result = aes_ecb(fd, pmsg, Xn);
-       if (!result)
-               goto done;
-
-       /* If AAD is being used to authenticate, include it here */
-       if (aad_len) {
-               l_put_be16(aad_len, pmsg);
-
-               for (i = 0; i < sizeof(uint16_t); i++)
-                       pmsg[i] = Xn[i] ^ pmsg[i];
 
-               j = 0;
-               aad_len += sizeof(uint16_t);
-               while (aad_len > 16) {
-                       do {
-                               pmsg[i] = Xn[i] ^ aad[j];
-                               i++, j++;
-                       } while (i < 16);
+       cipher = l_aead_cipher_new(L_AEAD_CIPHER_AES_CCM, key, 16, mic_size);
 
-                       aad_len -= 16;
-                       i = 0;
+       result = l_aead_cipher_encrypt(cipher, msg, msg_len, aad, aad_len,
+                                       nonce, 13, out_msg, msg_len + mic_size);
 
-                       result = aes_ecb(fd, pmsg, Xn);
-                       if (!result)
-                               goto done;
-               }
-
-               for (i = 0; i < aad_len; i++, j++)
-                       pmsg[i] = Xn[i] ^ aad[j];
-
-               for (i = aad_len; i < 16; i++)
-                       pmsg[i] = Xn[i];
-
-               result = aes_ecb(fd, pmsg, Xn);
-               if (!result)
-                       goto done;
-       }
-
-       last_blk = msg_len % 16;
-       blk_cnt = (msg_len + 15) / 16;
-       if (!last_blk)
-               last_blk = 16;
-
-       for (j = 0; j < blk_cnt; j++) {
-               if (j + 1 == blk_cnt) {
-                       /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
-                       for (i = 0; i < last_blk; i++)
-                               pmsg[i] = Xn[i] ^ msg[(j * 16) + i];
-                       for (i = last_blk; i < 16; i++)
-                               pmsg[i] = Xn[i] ^ 0x00;
-
-                       result = aes_ecb(fd, pmsg, Xn);
-                       if (!result)
-                               goto done;
-
-                       /* MIC = C_mic ^ X_1 */
-                       for (i = 0; i < sizeof(mic); i++)
-                               mic[i] = cmic[i] ^ Xn[i];
-
-                       /* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
-                       pmsg[0] = 0x01;
-                       memcpy(pmsg + 1, nonce, 13);
-                       l_put_be16(j + 1, pmsg + 14);
-
-                       result = aes_ecb(fd, pmsg, cmsg);
-                       if (!result)
-                               goto done;
-
-                       if (out_msg) {
-                               /* Encrypted = Payload[0-15] ^ C_1 */
-                               for (i = 0; i < last_blk; i++)
-                                       out_msg[(j * 16) + i] =
-                                               msg[(j * 16) + i] ^ cmsg[i];
-
-                       }
-               } else {
-                       /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
-                       for (i = 0; i < 16; i++)
-                               pmsg[i] = Xn[i] ^ msg[(j * 16) + i];
-
-                       result = aes_ecb(fd, pmsg, Xn);
-                       if (!result)
-                               goto done;
-
-                       /* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
-                       pmsg[0] = 0x01;
-                       memcpy(pmsg + 1, nonce, 13);
-                       l_put_be16(j + 1, pmsg + 14);
-
-                       result = aes_ecb(fd, pmsg, cmsg);
-                       if (!result)
-                               goto done;
-
-                       if (out_msg) {
-                               /* Encrypted = Payload[0-15] ^ C_N */
-                               for (i = 0; i < 16; i++)
-                                       out_msg[(j * 16) + i] =
-                                               msg[(j * 16) + i] ^ cmsg[i];
-                       }
-
-               }
-       }
-
-       if (out_msg)
-               memcpy(out_msg + msg_len, mic, mic_size);
-
-       if (out_mic) {
-               switch (mic_size) {
-               case 4:
-                       *(uint32_t *)out_mic = l_get_be32(mic);
-                       break;
-               case 8:
-                       *(uint64_t *)out_mic = l_get_be64(mic);
-                       break;
-               default:
-                       /* Unsupported MIC size */
-                       result = false;
-               }
+       if (result && out_mic) {
+               if (mic_size == 4)
+                       *(uint32_t *)out_mic = l_get_be32(out_msg + msg_len);
+               else
+                       *(uint64_t *)out_mic = l_get_be64(out_msg + msg_len);
        }
 
-done:
-       aes_ecb_destroy(fd);
+       l_aead_cipher_free(cipher);
 
        return result;
 }
@@ -411,156 +131,26 @@ bool mesh_crypto_aes_ccm_decrypt(const uint8_t nonce[13], const uint8_t key[16],
                                uint8_t *out_msg,
                                void *out_mic, size_t mic_size)
 {
-       uint8_t msg[16], pmsg[16], cmic[16], cmsg[16], Xn[16];
-       uint8_t mic[16];
-       uint16_t msg_len = enc_msg_len - mic_size;
-       uint16_t last_blk, blk_cnt;
+       void *cipher;
        bool result;
-       size_t i, j;
-       int fd;
-
-       if (enc_msg_len < 5 || aad_len > 16)
-               return false;
-
-       fd = aes_ecb_setup(key);
-       if (fd < 0)
-               return false;
-
-       /* C_mic = e(AppKey, 0x01 || nonce || 0x0000) */
-       pmsg[0] = 0x01;
-       memcpy(pmsg + 1, nonce, 13);
-       l_put_be16(0x0000, pmsg + 14);
-
-       result = aes_ecb(fd, pmsg, cmic);
-       if (!result)
-               goto done;
-
-       /* X_0 = e(AppKey, 0x09 || nonce || length) */
-       if (mic_size == 8)
-               pmsg[0] = 0x19 | (aad_len ? 0x40 : 0x00);
-       else
-               pmsg[0] = 0x09 | (aad_len ? 0x40 : 0x00);
+       size_t out_msg_len = enc_msg_len - mic_size;
 
-       memcpy(pmsg + 1, nonce, 13);
-       l_put_be16(msg_len, pmsg + 14);
-
-       result = aes_ecb(fd, pmsg, Xn);
-       if (!result)
-               goto done;
-
-       /* If AAD is being used to authenticate, include it here */
-       if (aad_len) {
-               l_put_be16(aad_len, pmsg);
-
-               for (i = 0; i < sizeof(uint16_t); i++)
-                       pmsg[i] = Xn[i] ^ pmsg[i];
-
-               j = 0;
-               aad_len += sizeof(uint16_t);
-               while (aad_len > 16) {
-                       do {
-                               pmsg[i] = Xn[i] ^ aad[j];
-                               i++, j++;
-                       } while (i < 16);
-
-                       aad_len -= 16;
-                       i = 0;
-
-                       result = aes_ecb(fd, pmsg, Xn);
-                       if (!result)
-                               goto done;
-               }
+       cipher = l_aead_cipher_new(L_AEAD_CIPHER_AES_CCM, key, 16, mic_size);
 
-               for (i = 0; i < aad_len; i++, j++)
-                       pmsg[i] = Xn[i] ^ aad[j];
+       result = l_aead_cipher_decrypt(cipher, enc_msg, enc_msg_len,
+                                                       aad, aad_len, nonce, 13,
+                                                       out_msg, out_msg_len);
 
-               for (i = aad_len; i < 16; i++)
-                       pmsg[i] = Xn[i];
-
-               result = aes_ecb(fd, pmsg, Xn);
-               if (!result)
-                       goto done;
-       }
-
-       last_blk = msg_len % 16;
-       blk_cnt = (msg_len + 15) / 16;
-       if (!last_blk)
-               last_blk = 16;
-
-       for (j = 0; j < blk_cnt; j++) {
-               if (j + 1 == blk_cnt) {
-                       /* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
-                       pmsg[0] = 0x01;
-                       memcpy(pmsg + 1, nonce, 13);
-                       l_put_be16(j + 1, pmsg + 14);
-
-                       result = aes_ecb(fd, pmsg, cmsg);
-                       if (!result)
-                               goto done;
-
-                       /* Encrypted = Payload[0-15] ^ C_1 */
-                       for (i = 0; i < last_blk; i++)
-                               msg[i] = enc_msg[(j * 16) + i] ^ cmsg[i];
-
-                       if (out_msg)
-                               memcpy(out_msg + (j * 16), msg, last_blk);
-
-                       /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
-                       for (i = 0; i < last_blk; i++)
-                               pmsg[i] = Xn[i] ^ msg[i];
-                       for (i = last_blk; i < 16; i++)
-                               pmsg[i] = Xn[i] ^ 0x00;
-
-                       result = aes_ecb(fd, pmsg, Xn);
-                       if (!result)
-                               goto done;
-
-                       /* MIC = C_mic ^ X_1 */
-                       for (i = 0; i < sizeof(mic); i++)
-                               mic[i] = cmic[i] ^ Xn[i];
-               } else {
-                       /* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
-                       pmsg[0] = 0x01;
-                       memcpy(pmsg + 1, nonce, 13);
-                       l_put_be16(j + 1, pmsg + 14);
-
-                       result = aes_ecb(fd, pmsg, cmsg);
-                       if (!result)
-                               goto done;
-
-                       /* Encrypted = Payload[0-15] ^ C_1 */
-                       for (i = 0; i < 16; i++)
-                               msg[i] = enc_msg[(j * 16) + i] ^ cmsg[i];
-
-                       if (out_msg)
-                               memcpy(out_msg + (j * 16), msg, 16);
-
-                       /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
-                       for (i = 0; i < 16; i++)
-                               pmsg[i] = Xn[i] ^ msg[i];
-
-                       result = aes_ecb(fd, pmsg, Xn);
-                       if (!result)
-                               goto done;
-               }
-       }
-
-       if (out_mic) {
-               switch (mic_size) {
-               case 4:
-                       *(uint32_t *)out_mic = l_get_be32(mic);
-                       break;
-               case 8:
-                       *(uint64_t *)out_mic = l_get_be64(mic);
-                       break;
-               default:
-                       /* Unsupported MIC size */
-                       result = false;
-               }
+       if (result && out_mic) {
+               if (mic_size == 4)
+                       *(uint32_t *)out_mic =
+                               l_get_be32(enc_msg + enc_msg_len - mic_size);
+               else
+                       *(uint64_t *)out_mic =
+                               l_get_be64(enc_msg + enc_msg_len - mic_size);
        }
 
-done:
-       aes_ecb_destroy(fd);
+       l_aead_cipher_free(cipher);
 
        return result;
 }
@@ -581,7 +171,7 @@ bool mesh_crypto_k2(const uint8_t n[16], const uint8_t *p, size_t p_len,
                                                        uint8_t enc_key[16],
                                                        uint8_t priv_key[16])
 {
-       int fd;
+       void *checksum;
        uint8_t output[16];
        uint8_t t[16];
        uint8_t *stage;
@@ -597,14 +187,14 @@ bool mesh_crypto_k2(const uint8_t n[16], const uint8_t *p, size_t p_len,
        if (!aes_cmac_one(stage, n, 16, t))
                goto fail;
 
-       fd = aes_cmac_N_start(t);
-       if (fd < 0)
+       checksum = l_checksum_new_cmac_aes(t, 16);
+       if (!checksum)
                goto fail;
 
        memcpy(stage, p, p_len);
        stage[p_len] = 1;
 
-       if (!aes_cmac(fd, stage, p_len + 1, output))
+       if (!aes_cmac(checksum, stage, p_len + 1, output))
                goto done;
 
        net_id[0] = output[15] & 0x7f;
@@ -613,7 +203,7 @@ bool mesh_crypto_k2(const uint8_t n[16], const uint8_t *p, size_t p_len,
        memcpy(stage + 16, p, p_len);
        stage[p_len + 16] = 2;
 
-       if (!aes_cmac(fd, stage, p_len + 16 + 1, output))
+       if (!aes_cmac(checksum, stage, p_len + 16 + 1, output))
                goto done;
 
        memcpy(enc_key, output, 16);
@@ -622,14 +212,14 @@ bool mesh_crypto_k2(const uint8_t n[16], const uint8_t *p, size_t p_len,
        memcpy(stage + 16, p, p_len);
        stage[p_len + 16] = 3;
 
-       if (!aes_cmac(fd, stage, p_len + 16 + 1, output))
+       if (!aes_cmac(checksum, stage, p_len + 16 + 1, output))
                goto done;
 
        memcpy(priv_key, output, 16);
        success = true;
 
 done:
-       aes_cmac_destroy(fd);
+       l_checksum_free(checksum);
 fail:
        l_free(stage);