"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-af-alg.c" (15 Mar 2019, 14863 Bytes) of package /linux/privat/stress-ng-0.09.56.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "stress-af-alg.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.09.52_vs_0.09.54.

    1 /*
    2  * Copyright (C) 2013-2019 Canonical, Ltd.
    3  *
    4  * This program is free software; you can redistribute it and/or
    5  * modify it under the terms of the GNU General Public License
    6  * as published by the Free Software Foundation; either version 2
    7  * of the License, or (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not, write to the Free Software
   16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   17  *
   18  * This code is a complete clean re-write of the stress tool by
   19  * Colin Ian King <colin.king@canonical.com> and attempts to be
   20  * backwardly compatible with the stress tool by Amos Waterland
   21  * <apw@rossby.metr.ou.edu> but has more stress tests and more
   22  * functionality.
   23  *
   24  */
   25 #include "stress-ng.h"
   26 
   27 #if defined(HAVE_LINUX_IF_ALG_H) && \
   28     defined(HAVE_LINUX_SOCKET_H) && \
   29     defined(AF_ALG)
   30 
   31 #if !defined(SOL_ALG)
   32 #define SOL_ALG             (279)
   33 #endif
   34 #define DATA_LEN            (1024)
   35 #define MAX_AF_ALG_RETRIES      (25)
   36 
   37 #define SNG_CRC32C_DIGEST_SIZE      (4)
   38 #define SNG_SHA1_DIGEST_SIZE        (20)
   39 #define SNG_SHA224_DIGEST_SIZE      (28)
   40 #define SNG_SHA256_DIGEST_SIZE      (32)
   41 #define SNG_SHA384_DIGEST_SIZE      (48)
   42 #define SNG_SHA512_DIGEST_SIZE      (64)
   43 #define SNG_MD4_DIGEST_SIZE     (16)
   44 #define SNG_MD5_DIGEST_SIZE     (16)
   45 #define SNG_RMD128_DIGEST_SIZE      (16)
   46 #define SNG_RMD160_DIGEST_SIZE      (20)
   47 #define SNG_RMD256_DIGEST_SIZE      (32)
   48 #define SNG_RMD320_DIGEST_SIZE      (40)
   49 #define SNG_WP256_DIGEST_SIZE       (32)
   50 #define SNG_WP384_DIGEST_SIZE       (48)
   51 #define SNG_WP512_DIGEST_SIZE       (64)
   52 #define SNG_TGR128_DIGEST_SIZE      (16)
   53 #define SNG_TGR160_DIGEST_SIZE      (20)
   54 #define SNG_TGR192_DIGEST_SIZE      (24)
   55 #define SNG_XOR_DIGEST_SIZE     (4096)
   56 #define SNG_CRC_T10DIF_DIGEST_SIZE  (2)
   57 
   58 #define SNG_CRC32C_BLOCK_SIZE       (1)
   59 #define SNG_AES_BLOCK_SIZE      (16)
   60 #define SNG_TF_BLOCK_SIZE       (16)
   61 #define SNG_SERPENT_BLOCK_SIZE      (16)
   62 #define SNG_CAST6_BLOCK_SIZE        (16)
   63 #define SNG_CAMELLIA_BLOCK_SIZE     (16)
   64 #define SNG_SALSA20_BLOCK_SIZE      (8)
   65 #define SNG_GHASH_BLOCK_SIZE        (16)
   66 #define SNG_TWOFISH_BLOCK_SIZE      (16)
   67 
   68 #define SNG_AES_MAX_KEY_SIZE        (32)
   69 #define SNG_TF_MAX_KEY_SIZE     (32)
   70 #define SNG_SERPENT_MAX_KEY_SIZE    (32)
   71 #define SNG_CAST6_MAX_KEY_SIZE      (32)
   72 #define SNG_CAMELLIA_MAX_KEY_SIZE   (32)
   73 #define SNG_SALSA20_MAX_KEY_SIZE    (32)
   74 #define SNG_GHASH_MAX_KEY_SIZE      (16)
   75 #define SNG_TWOFISH_MAX_KEY_SIZE    (32)
   76 
   77 /* See https://lwn.net/Articles/410833/ */
   78 
   79 typedef struct {
   80     const char *name;
   81     const ssize_t digest_size;
   82     bool skip;
   83 } alg_hash_info_t;
   84 
   85 typedef struct {
   86     const char *name;
   87     const ssize_t block_size;
   88     const ssize_t key_size;
   89     bool skip;
   90 } alg_cipher_info_t;
   91 
   92 typedef struct {
   93     const char *name;
   94 } alg_rng_info_t;
   95 
   96 static alg_hash_info_t algo_hash_info[] = {
   97     { "crc32c", SNG_CRC32C_DIGEST_SIZE,     false },
   98     { "sha1",   SNG_SHA1_DIGEST_SIZE,       false },
   99     { "sha224", SNG_SHA224_DIGEST_SIZE,     false },
  100     { "sha256", SNG_SHA256_DIGEST_SIZE,     false },
  101     { "sha384", SNG_SHA384_DIGEST_SIZE,     false },
  102     { "sha512", SNG_SHA512_DIGEST_SIZE,     false },
  103     { "md4",    SNG_MD4_DIGEST_SIZE,        false },
  104     { "md5",    SNG_MD5_DIGEST_SIZE,        false },
  105     { "rmd128", SNG_RMD128_DIGEST_SIZE,     false },
  106     { "rmd160", SNG_RMD160_DIGEST_SIZE,     false },
  107     { "rmd256", SNG_RMD256_DIGEST_SIZE,     false },
  108     { "rmd320", SNG_RMD320_DIGEST_SIZE,     false },
  109     { "wp256",  SNG_WP256_DIGEST_SIZE,      false },
  110     { "wp384",  SNG_WP384_DIGEST_SIZE,      false },
  111     { "wp512",  SNG_WP512_DIGEST_SIZE,      false },
  112     { "tgr128", SNG_TGR128_DIGEST_SIZE,     false },
  113     { "tgr160", SNG_TGR160_DIGEST_SIZE,     false },
  114     { "tgr192", SNG_TGR192_DIGEST_SIZE,     false },
  115     { "xor",    SNG_XOR_DIGEST_SIZE,        false },
  116     { "crct10dif",  SNG_CRC_T10DIF_DIGEST_SIZE, false },
  117 };
  118 
  119 static alg_cipher_info_t algo_cipher_info[] = {
  120     { "cbc(aes)",       SNG_AES_BLOCK_SIZE, SNG_AES_MAX_KEY_SIZE,       false },
  121     { "lrw(aes)",       SNG_AES_BLOCK_SIZE, SNG_AES_MAX_KEY_SIZE,       false },
  122     { "ofb(aes)",       SNG_AES_BLOCK_SIZE, SNG_AES_MAX_KEY_SIZE,       false },
  123     { "xts(twofish)",   SNG_TF_BLOCK_SIZE,  SNG_TF_MAX_KEY_SIZE,        false },
  124     { "xts(serpent)",   SNG_SERPENT_BLOCK_SIZE, SNG_SERPENT_MAX_KEY_SIZE,   false },
  125     { "xts(cast6)",     SNG_CAST6_BLOCK_SIZE,   SNG_CAST6_MAX_KEY_SIZE,     false },
  126     { "xts(camellia)",  SNG_CAMELLIA_BLOCK_SIZE,SNG_CAMELLIA_MAX_KEY_SIZE,  false },
  127     { "lrw(twofish)",   SNG_TF_BLOCK_SIZE,  SNG_TF_MAX_KEY_SIZE,        false },
  128     { "lrw(serpent)",   SNG_SERPENT_BLOCK_SIZE, SNG_SERPENT_MAX_KEY_SIZE,   false },
  129     { "lrw(cast6)",     SNG_CAST6_BLOCK_SIZE,   SNG_CAST6_MAX_KEY_SIZE,     false },
  130     { "lrw(camellia)",  SNG_CAMELLIA_BLOCK_SIZE,SNG_CAMELLIA_MAX_KEY_SIZE,  false },
  131     { "salsa20",        SNG_SALSA20_BLOCK_SIZE, SNG_SALSA20_MAX_KEY_SIZE,   false },
  132     { "ghash",      SNG_GHASH_BLOCK_SIZE,   SNG_GHASH_MAX_KEY_SIZE,     false },
  133     { "twofish",        SNG_TWOFISH_BLOCK_SIZE, SNG_TWOFISH_MAX_KEY_SIZE,   false },
  134 };
  135 
  136 static const alg_rng_info_t algo_rng_info[] = {
  137     { "jitterentropy_rng" }
  138 };
  139 
  140 static int stress_af_alg_hash(
  141     const args_t *args,
  142     const int sockfd,
  143     uint64_t *hashfails)
  144 {
  145     size_t i;
  146     bool bind_ok = false;
  147 
  148     for (i = 0; i < SIZEOF_ARRAY(algo_hash_info); i++) {
  149         int fd;
  150         ssize_t j;
  151         const ssize_t digest_size = algo_hash_info[i].digest_size;
  152         char input[DATA_LEN], digest[digest_size];
  153         struct sockaddr_alg sa;
  154 
  155         if (!keep_stressing())
  156             break;
  157         if (algo_hash_info[i].skip)
  158             continue;
  159 
  160         (void)memset(&sa, 0, sizeof(sa));
  161         sa.salg_family = AF_ALG;
  162         (void)shim_strlcpy((char *)sa.salg_type, "hash", sizeof(sa.salg_type));
  163         (void)shim_strlcpy((char *)sa.salg_name, algo_hash_info[i].name,
  164             sizeof(sa.salg_name) - 1);
  165 
  166         if (bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
  167             /* Perhaps the hash does not exist with this kernel */
  168             if ((errno == ENOENT) || (errno == EBUSY))
  169                 continue;
  170             pr_fail_err("bind");
  171             return EXIT_FAILURE;
  172         }
  173         bind_ok = true;
  174 
  175         if (!keep_stressing())
  176             break;
  177 
  178         fd = accept(sockfd, NULL, 0);
  179         if (fd < 0) {
  180             pr_fail_err("accept");
  181             return EXIT_FAILURE;
  182         }
  183 
  184         stress_strnrnd(input, sizeof(input));
  185 
  186         for (j = 32; j < (ssize_t)sizeof(input); j += 32) {
  187             if (!keep_stressing())
  188                 break;
  189             if (send(fd, input, j, 0) != j) {
  190                 if ((errno == 0) || (errno == ENOKEY) || (errno == ENOENT)) {
  191                     algo_hash_info[i].skip = true;
  192                     continue;
  193                 }
  194                 pr_fail("%s: send using %s failed: errno=%d (%s)\n",
  195                     args->name, algo_hash_info[i].name,
  196                     errno, strerror(errno));
  197                 (void)close(fd);
  198                 return EXIT_FAILURE;
  199             }
  200             if (recv(fd, digest, digest_size, MSG_WAITALL) != digest_size) {
  201                 pr_fail("%s: recv using %s failed: errno=%d (%s)\n",
  202                     args->name, algo_hash_info[i].name,
  203                     errno, strerror(errno));
  204                 (void)close(fd);
  205                 return EXIT_FAILURE;
  206             }
  207             inc_counter(args);
  208             if (args->max_ops && (get_counter(args) >= args->max_ops)) {
  209                 (void)close(fd);
  210                 return EXIT_SUCCESS;
  211             }
  212         }
  213         (void)close(fd);
  214     }
  215     if (!bind_ok)
  216         (*hashfails)++;
  217 
  218     return EXIT_SUCCESS;
  219 }
  220 
  221 static int stress_af_alg_cipher(
  222     const args_t *args,
  223     const int sockfd,
  224     uint64_t *cipherfails)
  225 {
  226     size_t i;
  227     bool bind_ok = false;
  228 
  229     for (i = 0; i < SIZEOF_ARRAY(algo_cipher_info); i++) {
  230         int fd;
  231         ssize_t j;
  232         struct sockaddr_alg sa;
  233         const ssize_t key_size = algo_cipher_info[i].key_size;
  234         const ssize_t block_size = algo_cipher_info[i].block_size;
  235         const ssize_t iv_size = block_size;
  236         char key[key_size];
  237         char input[DATA_LEN], output[DATA_LEN];
  238 
  239         if (!keep_stressing())
  240             break;
  241         if (algo_cipher_info[i].skip)
  242             continue;
  243 
  244         (void)memset(&sa, 0, sizeof(sa));
  245         sa.salg_family = AF_ALG;
  246         (void)shim_strlcpy((char *)sa.salg_type, "skcipher", sizeof(sa.salg_type));
  247         (void)shim_strlcpy((char *)sa.salg_name, algo_cipher_info[i].name,
  248             sizeof(sa.salg_name) - 1);
  249 
  250         if (bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
  251             /* Perhaps the cipher does not exist with this kernel */
  252             if ((errno == 0) || (errno == ENOKEY) || (errno == ENOENT) || (errno == EBUSY)) {
  253                 algo_cipher_info[i].skip = true;
  254                 continue;
  255             }
  256             pr_fail_err("bind");
  257             return EXIT_FAILURE;
  258         }
  259         bind_ok = true;
  260 
  261         stress_strnrnd(key, sizeof(key));
  262         if (setsockopt(sockfd, SOL_ALG, ALG_SET_KEY, key, sizeof(key)) < 0) {
  263             pr_fail_err("setsockopt");
  264             return EXIT_FAILURE;
  265         }
  266 
  267         if (!keep_stressing())
  268             break;
  269 
  270         fd = accept(sockfd, NULL, 0);
  271         if (fd < 0) {
  272             pr_fail_err("accept");
  273             return EXIT_FAILURE;
  274         }
  275 
  276         for (j = 32; j < (ssize_t)sizeof(input); j += 32) {
  277             __u32 *u32ptr;
  278             struct msghdr msg;
  279             struct cmsghdr *cmsg;
  280             char cbuf[CMSG_SPACE(sizeof(__u32)) +
  281                 CMSG_SPACE(4) + CMSG_SPACE(iv_size)];
  282             struct af_alg_iv *iv;   /* Initialisation Vector */
  283             struct iovec iov;
  284 
  285             if (!keep_stressing())
  286                 break;
  287             (void)memset(&msg, 0, sizeof(msg));
  288             (void)memset(cbuf, 0, sizeof(cbuf));
  289 
  290             msg.msg_control = cbuf;
  291             msg.msg_controllen = sizeof(cbuf);
  292 
  293             /* Chosen operation - ENCRYPT */
  294             cmsg = CMSG_FIRSTHDR(&msg);
  295             /* Keep static analysis happy */
  296             if (!cmsg) {
  297                 (void)close(fd);
  298                 pr_fail_err("null cmsg");
  299                 return EXIT_FAILURE;
  300             }
  301             cmsg->cmsg_level = SOL_ALG;
  302             cmsg->cmsg_type = ALG_SET_OP;
  303             cmsg->cmsg_len = CMSG_LEN(4);
  304             u32ptr = (__u32 *)CMSG_DATA(cmsg);
  305             *u32ptr = ALG_OP_ENCRYPT;
  306 
  307             /* Set up random Initialization Vector */
  308             cmsg = CMSG_NXTHDR(&msg, cmsg);
  309             if (!cmsg)
  310                 break;
  311             cmsg->cmsg_level = SOL_ALG;
  312             cmsg->cmsg_type = ALG_SET_IV;
  313             cmsg->cmsg_len = CMSG_LEN(4) + CMSG_LEN(iv_size);
  314             iv = (void *)CMSG_DATA(cmsg);
  315             iv->ivlen = iv_size;
  316 
  317             stress_strnrnd((char *)iv->iv, iv_size);
  318 
  319             /* Generate random message to encrypt */
  320             stress_strnrnd(input, sizeof(input));
  321             iov.iov_base = input;
  322             iov.iov_len = sizeof(input);
  323 
  324             msg.msg_iov = &iov;
  325             msg.msg_iovlen = 1;
  326 
  327             if (sendmsg(fd, &msg, 0) < 0) {
  328                 if (errno == ENOMEM)
  329                     break;
  330                 pr_fail("%s: sendmsg using %s failed: errno=%d (%s)\n",
  331                     args->name, algo_cipher_info[i].name,
  332                     errno, strerror(errno));
  333                 (void)close(fd);
  334                 return EXIT_FAILURE;
  335             }
  336             if (read(fd, output, sizeof(output)) != sizeof(output)) {
  337                 pr_fail("%s: read using %s failed: errno=%d (%s)\n",
  338                     args->name, algo_cipher_info[i].name,
  339                     errno, strerror(errno));
  340                 (void)close(fd);
  341                 return EXIT_FAILURE;
  342             }
  343 
  344             /* Chosen operation - DECRYPT */
  345             cmsg = CMSG_FIRSTHDR(&msg);
  346             if (!cmsg)
  347                 break;
  348             cmsg->cmsg_level = SOL_ALG;
  349             cmsg->cmsg_type = ALG_SET_OP;
  350             cmsg->cmsg_len = CMSG_LEN(4);
  351             u32ptr = (__u32 *)CMSG_DATA(cmsg);
  352             *u32ptr = ALG_OP_DECRYPT;
  353 
  354             /* Set up random Initialization Vector */
  355             cmsg = CMSG_NXTHDR(&msg, cmsg);
  356             if (!cmsg)
  357                 break;
  358 
  359             cmsg->cmsg_level = SOL_ALG;
  360             cmsg->cmsg_type = ALG_SET_IV;
  361             cmsg->cmsg_len = CMSG_LEN(4) + CMSG_LEN(iv_size);
  362             iv = (void *)CMSG_DATA(cmsg);
  363             iv->ivlen = iv_size;
  364 
  365             iov.iov_base = output;
  366             iov.iov_len = sizeof(output);
  367 
  368             msg.msg_iov = &iov;
  369             msg.msg_iovlen = 1;
  370 
  371             if (sendmsg(fd, &msg, 0) < 0) {
  372                 if (errno == ENOMEM)
  373                     break;
  374                 pr_fail("%s: sendmsg using %s failed: errno=%d (%s)\n",
  375                     args->name, algo_cipher_info[i].name,
  376                     errno, strerror(errno));
  377                 (void)close(fd);
  378                 return EXIT_FAILURE;
  379             }
  380             if (read(fd, output, sizeof(output)) != sizeof(output)) {
  381                 pr_fail("%s: read using %s failed: errno=%d (%s)\n",
  382                     args->name, algo_cipher_info[i].name,
  383                     errno, strerror(errno));
  384                 (void)close(fd);
  385                 return EXIT_FAILURE;
  386             } else {
  387                 if (memcmp(input, output, sizeof(input))) {
  388                     pr_err("%s: decrypted data "
  389                         "different from original data "
  390                         "using %s\n",
  391                         args->name,  algo_hash_info[i].name);
  392                 }
  393             }
  394         }
  395 
  396         (void)close(fd);
  397         inc_counter(args);
  398         if (args->max_ops && (get_counter(args) >= args->max_ops))
  399             return EXIT_SUCCESS;
  400     }
  401     if (!bind_ok)
  402         (*cipherfails)++;
  403 
  404     return EXIT_SUCCESS;
  405 }
  406 
  407 static int stress_af_alg_rng(
  408     const args_t *args,
  409     const int sockfd,
  410     uint64_t *rngfails)
  411 {
  412     size_t i;
  413     bool bind_ok = false;
  414 
  415     for (i = 0; i < SIZEOF_ARRAY(algo_rng_info); i++) {
  416         int fd;
  417         ssize_t j;
  418         struct sockaddr_alg sa;
  419 
  420         if (!keep_stressing())
  421             break;
  422         (void)memset(&sa, 0, sizeof(sa));
  423         sa.salg_family = AF_ALG;
  424         (void)shim_strlcpy((char *)sa.salg_type, "rng", sizeof(sa.salg_type));
  425         (void)shim_strlcpy((char *)sa.salg_name, algo_rng_info[i].name,
  426             sizeof(sa.salg_name) - 1);
  427 
  428         if (bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
  429             /* Perhaps the rng does not exist with this kernel */
  430             if ((errno == ENOENT) || (errno == EBUSY))
  431                 continue;
  432             pr_fail_err("bind");
  433             return EXIT_FAILURE;
  434         }
  435         bind_ok = true;
  436 
  437         if (!keep_stressing())
  438             break;
  439 
  440         fd = accept(sockfd, NULL, 0);
  441         if (fd < 0) {
  442             pr_fail_err("accept");
  443             return EXIT_FAILURE;
  444         }
  445 
  446         for (j = 0; j < 16; j++) {
  447             char output[16];
  448 
  449             if (!keep_stressing())
  450                 break;
  451             if (read(fd, output, sizeof(output)) != sizeof(output)) {
  452                 pr_fail_err("read");
  453                 (void)close(fd);
  454                 return EXIT_FAILURE;
  455             }
  456             inc_counter(args);
  457             if (args->max_ops && (get_counter(args) >= args->max_ops)) {
  458                 (void)close(fd);
  459                 return EXIT_SUCCESS;
  460             }
  461         }
  462         (void)close(fd);
  463     }
  464     if (!bind_ok)
  465         (*rngfails)++;
  466 
  467     return EXIT_SUCCESS;
  468 }
  469 
  470 /*
  471  *  stress_af_alg()
  472  *  stress socket AF_ALG domain
  473  */
  474 static int stress_af_alg(const args_t *args)
  475 {
  476     int sockfd = -1, rc = EXIT_FAILURE;
  477     int retries = MAX_AF_ALG_RETRIES;
  478     uint64_t hashfails = 0, cipherfails = 0, rngfails = 0;
  479 
  480     for (;;) {
  481         sockfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
  482         if (sockfd >= 0)
  483             break;
  484 
  485         retries--;
  486         if ((!g_keep_stressing_flag) || (retries < 0) || (errno != EAFNOSUPPORT)) {
  487             if (errno == EAFNOSUPPORT) {
  488                 /*
  489                  *  If we got got here, the protocol is not supported
  490                  *  so mark it as not implemented and skip the test
  491                  */
  492                 return EXIT_NOT_IMPLEMENTED;
  493             }
  494             pr_fail_err("socket");
  495             return rc;
  496         }
  497         /*
  498          * We may need to retry on EAFNOSUPPORT
  499          * as udev may have to load in some
  500          * cipher modules which can be racy or
  501          * take some time
  502          */
  503         (void)shim_usleep(200000);
  504     }
  505 
  506     do {
  507         rc = stress_af_alg_hash(args, sockfd, &hashfails);
  508         if (rc == EXIT_FAILURE)
  509             goto tidy;
  510         rc = stress_af_alg_cipher(args, sockfd, &cipherfails);
  511         if (rc == EXIT_FAILURE)
  512             goto tidy;
  513         rc = stress_af_alg_rng(args, sockfd, &rngfails);
  514         if (rc == EXIT_FAILURE)
  515             goto tidy;
  516     } while (keep_stressing());
  517 
  518     if (hashfails | cipherfails | rngfails)
  519         pr_dbg("%s: bind failed with ENOENT on all hashes (%"
  520             PRIu64 " times), ciphers (%" PRIu64 " times), "
  521             "prngs (%" PRIu64 " times)\n",
  522             args->name, hashfails, cipherfails, rngfails);
  523     rc = EXIT_SUCCESS;
  524 tidy:
  525     (void)close(sockfd);
  526 
  527     return rc;
  528 }
  529 
  530 stressor_info_t stress_af_alg_info = {
  531     .stressor = stress_af_alg,
  532     .class = CLASS_CPU | CLASS_OS
  533 };
  534 
  535 #else
  536 stressor_info_t stress_af_alg_info = {
  537     .stressor = stress_not_implemented,
  538     .class = CLASS_CPU | CLASS_OS
  539 };
  540 #endif