qemu/crypto/afalg.c
<<
>>
Prefs
   1/*
   2 * QEMU Crypto af_alg support
   3 *
   4 * Copyright (c) 2017 HUAWEI TECHNOLOGIES CO., LTD.
   5 *
   6 * Authors:
   7 *    Longpeng(Mike) <longpeng2@huawei.com>
   8 *
   9 * This work is licensed under the terms of the GNU GPL, version 2 or
  10 * (at your option) any later version.  See the COPYING file in the
  11 * top-level directory.
  12 */
  13#include "qemu/osdep.h"
  14#include "qemu/cutils.h"
  15#include "qemu/sockets.h"
  16#include "qapi/error.h"
  17#include "afalgpriv.h"
  18
  19static bool
  20qcrypto_afalg_build_saddr(const char *type, const char *name,
  21                          struct sockaddr_alg *salg, Error **errp)
  22{
  23    salg->salg_family = AF_ALG;
  24
  25    if (strnlen(type, SALG_TYPE_LEN_MAX) >= SALG_TYPE_LEN_MAX) {
  26        error_setg(errp, "Afalg type(%s) is larger than %d bytes",
  27                   type, SALG_TYPE_LEN_MAX);
  28        return false;
  29    }
  30
  31    if (strnlen(name, SALG_NAME_LEN_MAX) >= SALG_NAME_LEN_MAX) {
  32        error_setg(errp, "Afalg name(%s) is larger than %d bytes",
  33                   name, SALG_NAME_LEN_MAX);
  34        return false;
  35    }
  36
  37    pstrcpy((char *)salg->salg_type, SALG_TYPE_LEN_MAX, type);
  38    pstrcpy((char *)salg->salg_name, SALG_NAME_LEN_MAX, name);
  39
  40    return true;
  41}
  42
  43static int
  44qcrypto_afalg_socket_bind(const char *type, const char *name,
  45                          Error **errp)
  46{
  47    int sbind;
  48    struct sockaddr_alg salg = {0};
  49
  50    if (!qcrypto_afalg_build_saddr(type, name, &salg, errp)) {
  51        return -1;
  52    }
  53
  54    sbind = qemu_socket(AF_ALG, SOCK_SEQPACKET, 0);
  55    if (sbind < 0) {
  56        error_setg_errno(errp, errno, "Failed to create socket");
  57        return -1;
  58    }
  59
  60    if (bind(sbind, (const struct sockaddr *)&salg, sizeof(salg)) != 0) {
  61        error_setg_errno(errp, errno, "Failed to bind socket");
  62        closesocket(sbind);
  63        return -1;
  64    }
  65
  66    return sbind;
  67}
  68
  69QCryptoAFAlg *
  70qcrypto_afalg_comm_alloc(const char *type, const char *name,
  71                         Error **errp)
  72{
  73    QCryptoAFAlg *afalg;
  74
  75    afalg = g_new0(QCryptoAFAlg, 1);
  76    /* initilize crypto API socket */
  77    afalg->opfd = -1;
  78    afalg->tfmfd = qcrypto_afalg_socket_bind(type, name, errp);
  79    if (afalg->tfmfd == -1) {
  80        goto error;
  81    }
  82
  83    afalg->opfd = qemu_accept(afalg->tfmfd, NULL, 0);
  84    if (afalg->opfd == -1) {
  85        error_setg_errno(errp, errno, "Failed to accept socket");
  86        goto error;
  87    }
  88
  89    return afalg;
  90
  91error:
  92    qcrypto_afalg_comm_free(afalg);
  93    return NULL;
  94}
  95
  96void qcrypto_afalg_comm_free(QCryptoAFAlg *afalg)
  97{
  98    if (!afalg) {
  99        return;
 100    }
 101
 102    if (afalg->msg) {
 103        g_free(afalg->msg->msg_control);
 104        g_free(afalg->msg);
 105    }
 106
 107    if (afalg->tfmfd != -1) {
 108        closesocket(afalg->tfmfd);
 109    }
 110
 111    if (afalg->opfd != -1) {
 112        closesocket(afalg->opfd);
 113    }
 114
 115    g_free(afalg);
 116}
 117